Filename | /Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/PPI/Statement/Compound.pm |
Statements | Executed 19239 statements in 83.3ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
2355 | 3 | 2 | 61.6ms | 108ms | type | PPI::Statement::Compound::
1775 | 1 | 1 | 2.24ms | 2.24ms | __LEXER__normal | PPI::Statement::Compound::
2823 | 2 | 1 | 1.63ms | 1.63ms | CORE:match (opcode) | PPI::Statement::Compound::
1 | 1 | 1 | 12µs | 23µs | BEGIN@53 | PPI::Statement::Compound::
1 | 1 | 1 | 11µs | 11µs | BEGIN@57 | PPI::Statement::Compound::
1 | 1 | 1 | 6µs | 46µs | BEGIN@56 | PPI::Statement::Compound::
1 | 1 | 1 | 3µs | 3µs | BEGIN@54 | PPI::Statement::Compound::
0 | 0 | 0 | 0s | 0s | _complete | PPI::Statement::Compound::
0 | 0 | 0 | 0s | 0s | scope | PPI::Statement::Compound::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package PPI::Statement::Compound; | ||||
2 | |||||
3 | =pod | ||||
4 | |||||
5 | =head1 NAME | ||||
6 | |||||
7 | PPI::Statement::Compound - Describes all compound statements | ||||
8 | |||||
9 | =head1 SYNOPSIS | ||||
10 | |||||
11 | # A compound if statement | ||||
12 | if ( foo ) { | ||||
13 | bar(); | ||||
14 | } else { | ||||
15 | baz(); | ||||
16 | } | ||||
17 | |||||
18 | # A compound loop statement | ||||
19 | foreach ( @list ) { | ||||
20 | bar($_); | ||||
21 | } | ||||
22 | |||||
23 | =head1 INHERITANCE | ||||
24 | |||||
25 | PPI::Statement::Compound | ||||
26 | isa PPI::Statement | ||||
27 | isa PPI::Node | ||||
28 | isa PPI::Element | ||||
29 | |||||
30 | =head1 DESCRIPTION | ||||
31 | |||||
32 | C<PPI::Statement::Compound> objects are used to describe all current forms | ||||
33 | of compound statements, as described in L<perlsyn>. | ||||
34 | |||||
35 | This covers blocks using C<if>, C<unless>, C<for>, C<foreach>, C<while>, | ||||
36 | and C<continue>. Please note this does B<not> cover "simple" statements | ||||
37 | with trailing conditions. Please note also that "do" is also not part of | ||||
38 | a compound statement. | ||||
39 | |||||
40 | # This is NOT a compound statement | ||||
41 | my $foo = 1 if $condition; | ||||
42 | |||||
43 | # This is also not a compound statement | ||||
44 | do { ... } until $condition; | ||||
45 | |||||
46 | =head1 METHODS | ||||
47 | |||||
48 | C<PPI::Statement::Compound> has a number of methods in addition to the | ||||
49 | standard L<PPI::Statement>, L<PPI::Node> and L<PPI::Element> methods. | ||||
50 | |||||
51 | =cut | ||||
52 | |||||
53 | 2 | 18µs | 2 | 34µs | # spent 23µs (12+11) within PPI::Statement::Compound::BEGIN@53 which was called:
# once (12µs+11µs) by PPI::Statement::BEGIN@163 at line 53 # spent 23µs making 1 call to PPI::Statement::Compound::BEGIN@53
# spent 11µs making 1 call to strict::import |
54 | 2 | 18µs | 1 | 3µs | # spent 3µs within PPI::Statement::Compound::BEGIN@54 which was called:
# once (3µs+0s) by PPI::Statement::BEGIN@163 at line 54 # spent 3µs making 1 call to PPI::Statement::Compound::BEGIN@54 |
55 | |||||
56 | 2 | 43µs | 2 | 85µs | # spent 46µs (6+40) within PPI::Statement::Compound::BEGIN@56 which was called:
# once (6µs+40µs) by PPI::Statement::BEGIN@163 at line 56 # spent 46µs making 1 call to PPI::Statement::Compound::BEGIN@56
# spent 40µs making 1 call to vars::import |
57 | # spent 11µs within PPI::Statement::Compound::BEGIN@57 which was called:
# once (11µs+0s) by PPI::Statement::BEGIN@163 at line 70 | ||||
58 | 1 | 400ns | $VERSION = '1.215'; | ||
59 | 1 | 5µs | @ISA = 'PPI::Statement'; | ||
60 | |||||
61 | # Keyword type map | ||||
62 | 1 | 9µs | %TYPES = ( | ||
63 | 'if' => 'if', | ||||
64 | 'unless' => 'if', | ||||
65 | 'while' => 'while', | ||||
66 | 'until' => 'while', | ||||
67 | 'for' => 'for', | ||||
68 | 'foreach' => 'foreach', | ||||
69 | ); | ||||
70 | 1 | 294µs | 1 | 11µs | } # spent 11µs making 1 call to PPI::Statement::Compound::BEGIN@57 |
71 | |||||
72 | # Lexer clues | ||||
73 | 1775 | 6.85ms | # spent 2.24ms within PPI::Statement::Compound::__LEXER__normal which was called 1775 times, avg 1µs/call:
# 1775 times (2.24ms+0s) by PPI::Lexer::_lex_statement at line 626 of PPI/Lexer.pm, avg 1µs/call | ||
74 | |||||
- - | |||||
79 | ##################################################################### | ||||
80 | # PPI::Statement::Compound analysis methods | ||||
81 | |||||
82 | =pod | ||||
83 | |||||
84 | =head2 type | ||||
85 | |||||
86 | The C<type> method returns the syntactic type of the compound statement. | ||||
87 | |||||
88 | There are four basic compound statement types. | ||||
89 | |||||
90 | The C<'if'> type includes all variations of the if and unless statements, | ||||
91 | including any C<'elsif'> or C<'else'> parts of the compound statement. | ||||
92 | |||||
93 | The C<'while'> type describes the standard while and until statements, but | ||||
94 | again does B<not> describes simple statements with a trailing while. | ||||
95 | |||||
96 | The C<'for'> type covers the C-style for loops, regardless of whether they | ||||
97 | were declared using C<'for'> or C<'foreach'>. | ||||
98 | |||||
99 | The C<'foreach'> type covers loops that iterate over collections, | ||||
100 | regardless of whether they were declared using C<'for'> or C<'foreach'>. | ||||
101 | |||||
102 | All of the compounds are a variation on one of these four. | ||||
103 | |||||
104 | Returns the simple string C<'if'>, C<'for'>, C<'foreach'> or C<'while'>, | ||||
105 | or C<undef> if the type cannot be determined. | ||||
106 | |||||
107 | =begin testing type 52 | ||||
108 | |||||
109 | my $Document = PPI::Document->new(\<<'END_PERL'); | ||||
110 | while (1) { } | ||||
111 | until (1) { } | ||||
112 | LABEL: while (1) { } | ||||
113 | LABEL: until (1) { } | ||||
114 | |||||
115 | if (1) { } | ||||
116 | unless (1) { } | ||||
117 | |||||
118 | for (@foo) { } | ||||
119 | foreach (@foo) { } | ||||
120 | for $x (@foo) { } | ||||
121 | foreach $x (@foo) { } | ||||
122 | for my $x (@foo) { } | ||||
123 | foreach my $x (@foo) { } | ||||
124 | for state $x (@foo) { } | ||||
125 | foreach state $x (@foo) { } | ||||
126 | LABEL: for (@foo) { } | ||||
127 | LABEL: foreach (@foo) { } | ||||
128 | LABEL: for $x (@foo) { } | ||||
129 | LABEL: foreach $x (@foo) { } | ||||
130 | LABEL: for my $x (@foo) { } | ||||
131 | LABEL: foreach my $x (@foo) { } | ||||
132 | LABEL: for state $x (@foo) { } | ||||
133 | LABEL: foreach state $x (@foo) { } | ||||
134 | |||||
135 | for qw{foo} { } | ||||
136 | foreach qw{foo} { } | ||||
137 | for $x qw{foo} { } | ||||
138 | foreach $x qw{foo} { } | ||||
139 | for my $x qw{foo} { } | ||||
140 | foreach my $x qw{foo} { } | ||||
141 | for state $x qw{foo} { } | ||||
142 | foreach state $x qw{foo} { } | ||||
143 | LABEL: for qw{foo} { } | ||||
144 | LABEL: foreach qw{foo} { } | ||||
145 | LABEL: for $x qw{foo} { } | ||||
146 | LABEL: foreach $x qw{foo} { } | ||||
147 | LABEL: for my $x qw{foo} { } | ||||
148 | LABEL: foreach my $x qw{foo} { } | ||||
149 | LABEL: for state $x qw{foo} { } | ||||
150 | LABEL: foreach state $x qw{foo} { } | ||||
151 | |||||
152 | for ( ; ; ) { } | ||||
153 | foreach ( ; ; ) { } | ||||
154 | for ($x = 0 ; $x < 1; $x++) { } | ||||
155 | foreach ($x = 0 ; $x < 1; $x++) { } | ||||
156 | for (my $x = 0 ; $x < 1; $x++) { } | ||||
157 | foreach (my $x = 0 ; $x < 1; $x++) { } | ||||
158 | LABEL: for ( ; ; ) { } | ||||
159 | LABEL: foreach ( ; ; ) { } | ||||
160 | LABEL: for ($x = 0 ; $x < 1; $x++) { } | ||||
161 | LABEL: foreach ($x = 0 ; $x < 1; $x++) { } | ||||
162 | LABEL: for (my $x = 0 ; $x < 1; $x++) { } | ||||
163 | LABEL: foreach (my $x = 0 ; $x < 1; $x++) { } | ||||
164 | END_PERL | ||||
165 | isa_ok( $Document, 'PPI::Document' ); | ||||
166 | |||||
167 | my $statements = $Document->find('Statement::Compound'); | ||||
168 | is( scalar @{$statements}, 50, 'Found the 50 test statements' ); | ||||
169 | |||||
170 | is( $statements->[0]->type, 'while', q<Type of while is "while"> ); | ||||
171 | is( $statements->[1]->type, 'while', q<Type of until is "while"> ); | ||||
172 | is( $statements->[2]->type, 'while', q<Type of while with label is "while"> ); | ||||
173 | is( $statements->[3]->type, 'while', q<Type of until with label is "while"> ); | ||||
174 | is( $statements->[4]->type, 'if', q<Type of if is "if"> ); | ||||
175 | is( $statements->[5]->type, 'if', q<Type of unless is "if"> ); | ||||
176 | |||||
177 | foreach my $index (6..37) { | ||||
178 | my $statement = $statements->[$index]; | ||||
179 | is( $statement->type, 'foreach', qq<Type is "foreach": $statement> ); | ||||
180 | } | ||||
181 | |||||
182 | foreach my $index (38..49) { | ||||
183 | my $statement = $statements->[$index]; | ||||
184 | is( $statement->type, 'for', qq<Type is "for": $statement> ); | ||||
185 | } | ||||
186 | |||||
187 | =end testing | ||||
188 | |||||
189 | =cut | ||||
190 | |||||
191 | # spent 108ms (61.6+46.0) within PPI::Statement::Compound::type which was called 2355 times, avg 46µs/call:
# 1768 times (47.0ms+30.3ms) by PPI::Lexer::_continues at line 733 of PPI/Lexer.pm, avg 44µs/call
# 504 times (8.13ms+13.3ms) by Perl::Critic::Policy::Variables::RequireLexicalLoopIterators::violates at line 51 of Perl/Critic/Policy/Variables/RequireLexicalLoopIterators.pm, avg 43µs/call
# 83 times (6.45ms+2.36ms) by PPI::Lexer::_round at line 999 of PPI/Lexer.pm, avg 106µs/call | ||||
192 | 2355 | 584µs | my $self = shift; | ||
193 | 2355 | 373µs | my $p = 0; # Child position | ||
194 | 2355 | 9.30ms | 4710 | 20.4ms | my $Element = $self->schild($p) or return undef; # spent 18.8ms making 2355 calls to PPI::Node::schild, avg 8µs/call
# spent 1.58ms making 2355 calls to PPI::Util::TRUE, avg 673ns/call |
195 | |||||
196 | # A labelled statement | ||||
197 | 2355 | 14.2ms | 2527 | 4.30ms | if ( $Element->isa('PPI::Token::Label') ) { # spent 2.95ms making 2355 calls to UNIVERSAL::isa, avg 1µs/call
# spent 1.30ms making 93 calls to PPI::Node::schild, avg 14µs/call
# spent 45µs making 79 calls to PPI::Util::TRUE, avg 575ns/call |
198 | $Element = $self->schild(++$p) or return 'label'; | ||||
199 | } | ||||
200 | |||||
201 | # Most simple cases | ||||
202 | 2341 | 3.13ms | 2341 | 9.58ms | my $content = $Element->content; # spent 6.18ms making 7 calls to PPI::Structure::content, avg 883µs/call
# spent 3.40ms making 2334 calls to PPI::Token::content, avg 1µs/call |
203 | 2341 | 16.3ms | 2341 | 1.24ms | if ( $content =~ /^for(?:each)?\z/ ) { # spent 1.24ms making 2341 calls to PPI::Statement::Compound::CORE:match, avg 529ns/call |
204 | 587 | 2.22ms | 1085 | 7.56ms | $Element = $self->schild(++$p) or return $content; # spent 7.26ms making 587 calls to PPI::Node::schild, avg 12µs/call
# spent 300µs making 498 calls to PPI::Util::TRUE, avg 602ns/call |
205 | 498 | 1.47ms | 498 | 425µs | if ( $Element->isa('PPI::Token') ) { # spent 349µs making 482 calls to UNIVERSAL::isa, avg 725ns/call
# spent 40µs making 8 calls to PPI::Structure::For::isa, avg 5µs/call
# spent 36µs making 8 calls to PPI::Structure::List::isa, avg 5µs/call |
206 | 482 | 11.7ms | 964 | 1.04ms | return 'foreach' if $Element->content =~ /^my|our|state\z/; # spent 646µs making 482 calls to PPI::Token::content, avg 1µs/call
# spent 391µs making 482 calls to PPI::Statement::Compound::CORE:match, avg 811ns/call |
207 | return 'foreach' if $Element->isa('PPI::Token::Symbol'); | ||||
208 | return 'foreach' if $Element->isa('PPI::Token::QuoteLike::Words'); | ||||
209 | } | ||||
210 | 16 | 36µs | 16 | 60µs | if ( $Element->isa('PPI::Structure::List') ) { # spent 32µs making 8 calls to PPI::Structure::For::isa, avg 4µs/call
# spent 28µs making 8 calls to PPI::Structure::List::isa, avg 4µs/call |
211 | return 'foreach'; | ||||
212 | } | ||||
213 | 8 | 20µs | return 'for'; | ||
214 | } | ||||
215 | 1754 | 16.7ms | 1754 | 1.38ms | return $TYPES{$content} if $Element->isa('PPI::Token::Word'); # spent 1.38ms making 1754 calls to UNIVERSAL::isa, avg 789ns/call |
216 | 7 | 40µs | 7 | 5µs | return 'continue' if $Element->isa('PPI::Structure::Block'); # spent 5µs making 7 calls to UNIVERSAL::isa, avg 700ns/call |
217 | |||||
218 | # Unknown (shouldn't exist?) | ||||
219 | undef; | ||||
220 | } | ||||
221 | |||||
- - | |||||
226 | ##################################################################### | ||||
227 | # PPI::Node Methods | ||||
228 | |||||
229 | sub scope { 1 } | ||||
230 | |||||
- - | |||||
235 | ##################################################################### | ||||
236 | # PPI::Element Methods | ||||
237 | |||||
238 | sub _complete { | ||||
239 | my $self = shift; | ||||
240 | my $type = $self->type or die "Illegal compound statement type"; | ||||
241 | |||||
242 | # Check the different types of compound statements | ||||
243 | if ( $type eq 'if' ) { | ||||
244 | # Unless the last significant child is a complete | ||||
245 | # block, it must be incomplete. | ||||
246 | my $child = $self->schild(-1) or return ''; | ||||
247 | $child->isa('PPI::Structure') or return ''; | ||||
248 | $child->braces eq '{}' or return ''; | ||||
249 | $child->_complete or return ''; | ||||
250 | |||||
251 | # It can STILL be | ||||
252 | } elsif ( $type eq 'while' ) { | ||||
253 | die "CODE INCOMPLETE"; | ||||
254 | } else { | ||||
255 | die "CODE INCOMPLETE"; | ||||
256 | } | ||||
257 | } | ||||
258 | |||||
259 | 1 | 2µs | 1; | ||
260 | |||||
261 | =pod | ||||
262 | |||||
263 | =head1 TO DO | ||||
264 | |||||
265 | - Write unit tests for this package | ||||
266 | |||||
267 | =head1 SUPPORT | ||||
268 | |||||
269 | See the L<support section|PPI/SUPPORT> in the main module. | ||||
270 | |||||
271 | =head1 AUTHOR | ||||
272 | |||||
273 | Adam Kennedy E<lt>adamk@cpan.orgE<gt> | ||||
274 | |||||
275 | =head1 COPYRIGHT | ||||
276 | |||||
277 | Copyright 2001 - 2011 Adam Kennedy. | ||||
278 | |||||
279 | This program is free software; you can redistribute | ||||
280 | it and/or modify it under the same terms as Perl itself. | ||||
281 | |||||
282 | The full text of the license can be found in the | ||||
283 | LICENSE file included with this module. | ||||
284 | |||||
285 | =cut | ||||
sub PPI::Statement::Compound::CORE:match; # opcode |