Filename | /usr/lib/perl5/Template/Directive.pm |
Statements | Executed 15989 statements in 73.5ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
915 | 2 | 2 | 23.0ms | 34.2ms | text | Template::Directive::
914 | 1 | 1 | 7.48ms | 41.7ms | textblock | Template::Directive::
1830 | 2 | 1 | 6.43ms | 6.43ms | CORE:subst (opcode) | Template::Directive::
670 | 2 | 2 | 6.35ms | 6.35ms | ident | Template::Directive::
2526 | 1 | 1 | 4.81ms | 4.81ms | CORE:substcont (opcode) | Template::Directive::
286 | 3 | 1 | 4.68ms | 4.68ms | if | Template::Directive::
417 | 2 | 1 | 4.40ms | 4.40ms | block | Template::Directive::
303 | 2 | 1 | 1.86ms | 1.86ms | get | Template::Directive::
74 | 1 | 1 | 1.60ms | 2.06ms | filter | Template::Directive::
27 | 1 | 1 | 1.12ms | 1.40ms | foreach | Template::Directive::
78 | 2 | 2 | 494µs | 494µs | args | Template::Directive::
8 | 1 | 1 | 347µs | 1.04ms | template | Template::Directive::
8 | 1 | 1 | 167µs | 698µs | CORE:match (opcode) | Template::Directive::
8 | 1 | 1 | 115µs | 193µs | include | Template::Directive::
8 | 1 | 1 | 78µs | 78µs | filenames | Template::Directive::
3 | 1 | 1 | 59µs | 87µs | set | Template::Directive::
1 | 1 | 1 | 52µs | 57µs | BEGIN@33 | Template::Directive::
3 | 1 | 1 | 27µs | 27µs | assign | Template::Directive::
1 | 1 | 1 | 18µs | 23µs | BEGIN@29 | Template::Directive::
1 | 1 | 1 | 17µs | 61µs | BEGIN@32 | Template::Directive::
1 | 1 | 1 | 12µs | 26µs | BEGIN@30 | Template::Directive::
1 | 1 | 1 | 12µs | 128µs | BEGIN@31 | Template::Directive::
1 | 1 | 1 | 8µs | 8µs | quoted | Template::Directive::
0 | 0 | 0 | 0s | 0s | OLD_break | Template::Directive::
0 | 0 | 0 | 0s | 0s | _init | Template::Directive::
0 | 0 | 0 | 0s | 0s | anon_block | Template::Directive::
0 | 0 | 0 | 0s | 0s | call | Template::Directive::
0 | 0 | 0 | 0s | 0s | capture | Template::Directive::
0 | 0 | 0 | 0s | 0s | clear | Template::Directive::
0 | 0 | 0 | 0s | 0s | debug | Template::Directive::
0 | 0 | 0 | 0s | 0s | default | Template::Directive::
0 | 0 | 0 | 0s | 0s | identref | Template::Directive::
0 | 0 | 0 | 0s | 0s | insert | Template::Directive::
0 | 0 | 0 | 0s | 0s | macro | Template::Directive::
0 | 0 | 0 | 0s | 0s | multi_wrapper | Template::Directive::
0 | 0 | 0 | 0s | 0s | next | Template::Directive::
0 | 0 | 0 | 0s | 0s | no_perl | Template::Directive::
0 | 0 | 0 | 0s | 0s | pad | Template::Directive::
0 | 0 | 0 | 0s | 0s | perl | Template::Directive::
0 | 0 | 0 | 0s | 0s | process | Template::Directive::
0 | 0 | 0 | 0s | 0s | rawperl | Template::Directive::
0 | 0 | 0 | 0s | 0s | return | Template::Directive::
0 | 0 | 0 | 0s | 0s | stop | Template::Directive::
0 | 0 | 0 | 0s | 0s | switch | Template::Directive::
0 | 0 | 0 | 0s | 0s | throw | Template::Directive::
0 | 0 | 0 | 0s | 0s | try | Template::Directive::
0 | 0 | 0 | 0s | 0s | use | Template::Directive::
0 | 0 | 0 | 0s | 0s | view | Template::Directive::
0 | 0 | 0 | 0s | 0s | while | Template::Directive::
0 | 0 | 0 | 0s | 0s | wrapper | Template::Directive::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | #================================================================= -*-Perl-*- | ||||
2 | # | ||||
3 | # Template::Directive | ||||
4 | # | ||||
5 | # DESCRIPTION | ||||
6 | # Factory module for constructing templates from Perl code. | ||||
7 | # | ||||
8 | # AUTHOR | ||||
9 | # Andy Wardley <abw@wardley.org> | ||||
10 | # | ||||
11 | # WARNING | ||||
12 | # Much of this module is hairy, even furry in places. It needs | ||||
13 | # a lot of tidying up and may even be moved into a different place | ||||
14 | # altogether. The generator code is often inefficient, particulary in | ||||
15 | # being very anal about pretty-printing the Perl code all neatly, but | ||||
16 | # at the moment, that's still high priority for the sake of easier | ||||
17 | # debugging. | ||||
18 | # | ||||
19 | # COPYRIGHT | ||||
20 | # Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved. | ||||
21 | # | ||||
22 | # This module is free software; you can redistribute it and/or | ||||
23 | # modify it under the same terms as Perl itself. | ||||
24 | # | ||||
25 | #============================================================================ | ||||
26 | |||||
27 | package Template::Directive; | ||||
28 | |||||
29 | 3 | 39µs | 2 | 27µs | # spent 23µs (18+4) within Template::Directive::BEGIN@29 which was called:
# once (18µs+4µs) by Template::Parser::BEGIN@40 at line 29 # spent 23µs making 1 call to Template::Directive::BEGIN@29
# spent 4µs making 1 call to strict::import |
30 | 3 | 33µs | 2 | 40µs | # spent 26µs (12+14) within Template::Directive::BEGIN@30 which was called:
# once (12µs+14µs) by Template::Parser::BEGIN@40 at line 30 # spent 26µs making 1 call to Template::Directive::BEGIN@30
# spent 14µs making 1 call to warnings::import |
31 | 3 | 36µs | 2 | 244µs | # spent 128µs (12+116) within Template::Directive::BEGIN@31 which was called:
# once (12µs+116µs) by Template::Parser::BEGIN@40 at line 31 # spent 128µs making 1 call to Template::Directive::BEGIN@31
# spent 116µs making 1 call to base::import |
32 | 3 | 47µs | 2 | 104µs | # spent 61µs (17+43) within Template::Directive::BEGIN@32 which was called:
# once (17µs+43µs) by Template::Parser::BEGIN@40 at line 32 # spent 61µs making 1 call to Template::Directive::BEGIN@32
# spent 43µs making 1 call to Exporter::import |
33 | 3 | 4.45ms | 2 | 62µs | # spent 57µs (52+5) within Template::Directive::BEGIN@33 which was called:
# once (52µs+5µs) by Template::Parser::BEGIN@40 at line 33 # spent 57µs making 1 call to Template::Directive::BEGIN@33
# spent 5µs making 1 call to UNIVERSAL::import |
34 | |||||
35 | 1 | 600ns | our $VERSION = 2.20; | ||
36 | 1 | 600ns | our $DEBUG = 0 unless defined $DEBUG; | ||
37 | 1 | 200ns | our $WHILE_MAX = 1000 unless defined $WHILE_MAX; | ||
38 | 1 | 200ns | our $PRETTY = 0 unless defined $PRETTY; | ||
39 | 1 | 400ns | our $OUTPUT = '$output .= '; | ||
40 | |||||
41 | |||||
42 | sub _init { | ||||
43 | my ($self, $config) = @_; | ||||
44 | $self->{ NAMESPACE } = $config->{ NAMESPACE }; | ||||
45 | return $self; | ||||
46 | } | ||||
47 | |||||
48 | |||||
49 | sub pad { | ||||
50 | my ($text, $pad) = @_; | ||||
51 | $pad = ' ' x ($pad * 4); | ||||
52 | $text =~ s/^(?!#line)/$pad/gm; | ||||
53 | $text; | ||||
54 | } | ||||
55 | |||||
56 | #======================================================================== | ||||
57 | # FACTORY METHODS | ||||
58 | # | ||||
59 | # These methods are called by the parser to construct directive instances. | ||||
60 | #======================================================================== | ||||
61 | |||||
62 | #------------------------------------------------------------------------ | ||||
63 | # template($block) | ||||
64 | #------------------------------------------------------------------------ | ||||
65 | |||||
66 | # spent 1.04ms (347µs+698µs) within Template::Directive::template which was called 8 times, avg 131µs/call:
# 8 times (347µs+698µs) by Template::Grammar::__ANON__[Parser.yp:64] at line 64 of Parser.yp, avg 131µs/call | ||||
67 | 8 | 45µs | my ($class, $block) = @_; | ||
68 | 8 | 3µs | $block = pad($block, 2) if $PRETTY; | ||
69 | |||||
70 | 8 | 222µs | 9 | 1.23ms | return "sub { return '' }" unless $block =~ /\S/; # spent 698µs making 8 calls to Template::Directive::CORE:match, avg 87µs/call
# spent 530µs making 1 call to utf8::SWASHNEW |
71 | |||||
72 | 8 | 259µs | return <<EOF; | ||
73 | sub { | ||||
74 | my \$context = shift || die "template sub called without context\\n"; | ||||
75 | my \$stash = \$context->stash; | ||||
76 | my \$output = ''; | ||||
77 | my \$_tt_error; | ||||
78 | |||||
79 | eval { BLOCK: { | ||||
80 | $block | ||||
81 | } }; | ||||
82 | if (\$@) { | ||||
83 | \$_tt_error = \$context->catch(\$@, \\\$output); | ||||
84 | die \$_tt_error unless \$_tt_error->type eq 'return'; | ||||
85 | } | ||||
86 | |||||
87 | return \$output; | ||||
88 | } | ||||
89 | EOF | ||||
90 | } | ||||
91 | |||||
92 | |||||
93 | #------------------------------------------------------------------------ | ||||
94 | # anon_block($block) [% BLOCK %] ... [% END %] | ||||
95 | #------------------------------------------------------------------------ | ||||
96 | |||||
97 | sub anon_block { | ||||
98 | my ($class, $block) = @_; | ||||
99 | $block = pad($block, 2) if $PRETTY; | ||||
100 | |||||
101 | return <<EOF; | ||||
102 | |||||
103 | # BLOCK | ||||
104 | $OUTPUT do { | ||||
105 | my \$output = ''; | ||||
106 | my \$_tt_error; | ||||
107 | |||||
108 | eval { BLOCK: { | ||||
109 | $block | ||||
110 | } }; | ||||
111 | if (\$@) { | ||||
112 | \$_tt_error = \$context->catch(\$@, \\\$output); | ||||
113 | die \$_tt_error unless \$_tt_error->type eq 'return'; | ||||
114 | } | ||||
115 | |||||
116 | \$output; | ||||
117 | }; | ||||
118 | EOF | ||||
119 | } | ||||
120 | |||||
121 | |||||
122 | #------------------------------------------------------------------------ | ||||
123 | # block($blocktext) | ||||
124 | #------------------------------------------------------------------------ | ||||
125 | |||||
126 | # spent 4.40ms within Template::Directive::block which was called 417 times, avg 11µs/call:
# 416 times (4.40ms+0s) by Template::Grammar::__ANON__[Parser.yp:67] at line 67 of Parser.yp, avg 11µs/call
# once (3µs+0s) by Template::Grammar::__ANON__[Parser.yp:68] at line 68 of Parser.yp | ||||
127 | 417 | 545µs | my ($class, $block) = @_; | ||
128 | 417 | 5.17ms | return join("\n", @{ $block || [] }); | ||
129 | } | ||||
130 | |||||
131 | |||||
132 | #------------------------------------------------------------------------ | ||||
133 | # textblock($text) | ||||
134 | #------------------------------------------------------------------------ | ||||
135 | |||||
136 | # spent 41.7ms (7.48+34.2) within Template::Directive::textblock which was called 914 times, avg 46µs/call:
# 914 times (7.48ms+34.2ms) by Template::Grammar::__ANON__[Parser.yp:76] at line 76 of Parser.yp, avg 46µs/call | ||||
137 | 914 | 1.04ms | my ($class, $text) = @_; | ||
138 | 914 | 6.20ms | 914 | 34.2ms | return "$OUTPUT " . &text($class, $text) . ';'; # spent 34.2ms making 914 calls to Template::Directive::text, avg 37µs/call |
139 | } | ||||
140 | |||||
141 | |||||
142 | #------------------------------------------------------------------------ | ||||
143 | # text($text) | ||||
144 | #------------------------------------------------------------------------ | ||||
145 | |||||
146 | # spent 34.2ms (23.0+11.2) within Template::Directive::text which was called 915 times, avg 37µs/call:
# 914 times (23.0ms+11.2ms) by Template::Directive::textblock at line 138, avg 37µs/call
# once (15µs+4µs) by Template::Grammar::__ANON__[Parser.yp:440] at line 440 of Parser.yp | ||||
147 | 915 | 971µs | my ($class, $text) = @_; | ||
148 | 915 | 1.86ms | for ($text) { | ||
149 | 915 | 20.6ms | 3441 | 8.19ms | s/(["\$\@\\])/\\$1/g; # spent 4.81ms making 2526 calls to Template::Directive::CORE:substcont, avg 2µs/call
# spent 3.38ms making 915 calls to Template::Directive::CORE:subst, avg 4µs/call |
150 | 915 | 7.52ms | 915 | 3.05ms | s/\n/\\n/g; # spent 3.05ms making 915 calls to Template::Directive::CORE:subst, avg 3µs/call |
151 | } | ||||
152 | 915 | 4.37ms | return '"' . $text . '"'; | ||
153 | } | ||||
154 | |||||
155 | |||||
156 | #------------------------------------------------------------------------ | ||||
157 | # quoted(\@items) "foo$bar" | ||||
158 | #------------------------------------------------------------------------ | ||||
159 | |||||
160 | # spent 8µs within Template::Directive::quoted which was called:
# once (8µs+0s) by Template::Grammar::__ANON__[Parser.yp:307] at line 307 of Parser.yp | ||||
161 | 1 | 2µs | my ($class, $items) = @_; | ||
162 | 1 | 900ns | return '' unless @$items; | ||
163 | 1 | 10µs | return ("('' . " . $items->[0] . ')') if scalar @$items == 1; | ||
164 | return '(' . join(' . ', @$items) . ')'; | ||||
165 | # my $r = '(' . join(' . ', @$items) . ' . "")'; | ||||
166 | # print STDERR "[$r]\n"; | ||||
167 | # return $r; | ||||
168 | } | ||||
169 | |||||
170 | |||||
171 | #------------------------------------------------------------------------ | ||||
172 | # ident(\@ident) foo.bar(baz) | ||||
173 | #------------------------------------------------------------------------ | ||||
174 | |||||
175 | # spent 6.35ms within Template::Directive::ident which was called 670 times, avg 9µs/call:
# 643 times (6.07ms+0s) by Template::Grammar::__ANON__[Parser.yp:305] at line 305 of Parser.yp, avg 9µs/call
# 27 times (281µs+0s) by Template::Directive::foreach at line 404, avg 10µs/call | ||||
176 | 670 | 808µs | my ($class, $ident) = @_; | ||
177 | 670 | 304µs | return "''" unless @$ident; | ||
178 | 670 | 171µs | my $ns; | ||
179 | |||||
180 | # does the first element of the identifier have a NAMESPACE | ||||
181 | # handler defined? | ||||
182 | 670 | 308µs | if (ref $class && @$ident > 2 && ($ns = $class->{ NAMESPACE })) { | ||
183 | my $key = $ident->[0]; | ||||
184 | $key =~ s/^'(.+)'$/$1/s; | ||||
185 | if ($ns = $ns->{ $key }) { | ||||
186 | return $ns->ident($ident); | ||||
187 | } | ||||
188 | } | ||||
189 | |||||
190 | 670 | 1.13ms | if (scalar @$ident <= 2 && ! $ident->[1]) { | ||
191 | $ident = $ident->[0]; | ||||
192 | } | ||||
193 | else { | ||||
194 | 270 | 1.07ms | $ident = '[' . join(', ', @$ident) . ']'; | ||
195 | } | ||||
196 | 670 | 4.52ms | return "\$stash->get($ident)"; | ||
197 | } | ||||
198 | |||||
199 | #------------------------------------------------------------------------ | ||||
200 | # identref(\@ident) \foo.bar(baz) | ||||
201 | #------------------------------------------------------------------------ | ||||
202 | |||||
203 | sub identref { | ||||
204 | my ($class, $ident) = @_; | ||||
205 | return "''" unless @$ident; | ||||
206 | if (scalar @$ident <= 2 && ! $ident->[1]) { | ||||
207 | $ident = $ident->[0]; | ||||
208 | } | ||||
209 | else { | ||||
210 | $ident = '[' . join(', ', @$ident) . ']'; | ||||
211 | } | ||||
212 | return "\$stash->getref($ident)"; | ||||
213 | } | ||||
214 | |||||
215 | |||||
216 | #------------------------------------------------------------------------ | ||||
217 | # assign(\@ident, $value, $default) foo = bar | ||||
218 | #------------------------------------------------------------------------ | ||||
219 | |||||
220 | # spent 27µs within Template::Directive::assign which was called 3 times, avg 9µs/call:
# 3 times (27µs+0s) by Template::Directive::set at line 294, avg 9µs/call | ||||
221 | 3 | 5µs | my ($class, $var, $val, $default) = @_; | ||
222 | |||||
223 | 3 | 6µs | if (ref $var) { | ||
224 | if (scalar @$var == 2 && ! $var->[1]) { | ||||
225 | $var = $var->[0]; | ||||
226 | } | ||||
227 | else { | ||||
228 | $var = '[' . join(', ', @$var) . ']'; | ||||
229 | } | ||||
230 | } | ||||
231 | 3 | 1µs | $val .= ', 1' if $default; | ||
232 | 3 | 21µs | return "\$stash->set($var, $val)"; | ||
233 | } | ||||
234 | |||||
235 | |||||
236 | #------------------------------------------------------------------------ | ||||
237 | # args(\@args) foo, bar, baz = qux | ||||
238 | #------------------------------------------------------------------------ | ||||
239 | |||||
240 | # spent 494µs within Template::Directive::args which was called 78 times, avg 6µs/call:
# 74 times (460µs+0s) by Template::Directive::filter at line 876, avg 6µs/call
# 4 times (33µs+0s) by Template::Grammar::__ANON__[Parser.yp:342] at line 342 of Parser.yp, avg 8µs/call | ||||
241 | 78 | 77µs | my ($class, $args) = @_; | ||
242 | 78 | 61µs | my $hash = shift @$args; | ||
243 | 78 | 67µs | push(@$args, '{ ' . join(', ', @$hash) . ' }') | ||
244 | if @$hash; | ||||
245 | |||||
246 | 78 | 498µs | return '0' unless @$args; | ||
247 | 6 | 52µs | return '[ ' . join(', ', @$args) . ' ]'; | ||
248 | } | ||||
249 | |||||
250 | #------------------------------------------------------------------------ | ||||
251 | # filenames(\@names) | ||||
252 | #------------------------------------------------------------------------ | ||||
253 | |||||
254 | # spent 78µs within Template::Directive::filenames which was called 8 times, avg 10µs/call:
# 8 times (78µs+0s) by Template::Directive::include at line 339, avg 10µs/call | ||||
255 | 8 | 11µs | my ($class, $names) = @_; | ||
256 | 8 | 12µs | if (@$names > 1) { | ||
257 | $names = '[ ' . join(', ', @$names) . ' ]'; | ||||
258 | } | ||||
259 | else { | ||||
260 | 8 | 8µs | $names = shift @$names; | ||
261 | } | ||||
262 | 8 | 56µs | return $names; | ||
263 | } | ||||
264 | |||||
265 | |||||
266 | #------------------------------------------------------------------------ | ||||
267 | # get($expr) [% foo %] | ||||
268 | #------------------------------------------------------------------------ | ||||
269 | |||||
270 | # spent 1.86ms within Template::Directive::get which was called 303 times, avg 6µs/call:
# 236 times (1.44ms+0s) by Template::Grammar::__ANON__[Parser.yp:90] at line 90 of Parser.yp, avg 6µs/call
# 67 times (416µs+0s) by Template::Grammar::__ANON__[Parser.yp:109] at line 109 of Parser.yp, avg 6µs/call | ||||
271 | 303 | 327µs | my ($class, $expr) = @_; | ||
272 | 303 | 2.31ms | return "$OUTPUT $expr;"; | ||
273 | } | ||||
274 | |||||
275 | |||||
276 | #------------------------------------------------------------------------ | ||||
277 | # call($expr) [% CALL bar %] | ||||
278 | #------------------------------------------------------------------------ | ||||
279 | |||||
280 | sub call { | ||||
281 | my ($class, $expr) = @_; | ||||
282 | $expr .= ';'; | ||||
283 | return $expr; | ||||
284 | } | ||||
285 | |||||
286 | |||||
287 | #------------------------------------------------------------------------ | ||||
288 | # set(\@setlist) [% foo = bar, baz = qux %] | ||||
289 | #------------------------------------------------------------------------ | ||||
290 | |||||
291 | # spent 87µs (59+27) within Template::Directive::set which was called 3 times, avg 29µs/call:
# 3 times (59µs+27µs) by Template::Grammar::__ANON__[Parser.yp:115] at line 115 of Parser.yp, avg 29µs/call | ||||
292 | 3 | 4µs | my ($class, $setlist) = @_; | ||
293 | 3 | 1µs | my $output; | ||
294 | 3 | 22µs | 3 | 27µs | while (my ($var, $val) = splice(@$setlist, 0, 2)) { # spent 27µs making 3 calls to Template::Directive::assign, avg 9µs/call |
295 | $output .= &assign($class, $var, $val) . ";\n"; | ||||
296 | } | ||||
297 | 3 | 10µs | chomp $output; | ||
298 | 3 | 11µs | return $output; | ||
299 | } | ||||
300 | |||||
301 | |||||
302 | #------------------------------------------------------------------------ | ||||
303 | # default(\@setlist) [% DEFAULT foo = bar, baz = qux %] | ||||
304 | #------------------------------------------------------------------------ | ||||
305 | |||||
306 | sub default { | ||||
307 | my ($class, $setlist) = @_; | ||||
308 | my $output; | ||||
309 | while (my ($var, $val) = splice(@$setlist, 0, 2)) { | ||||
310 | $output .= &assign($class, $var, $val, 1) . ";\n"; | ||||
311 | } | ||||
312 | chomp $output; | ||||
313 | return $output; | ||||
314 | } | ||||
315 | |||||
316 | |||||
317 | #------------------------------------------------------------------------ | ||||
318 | # insert(\@nameargs) [% INSERT file %] | ||||
319 | # # => [ [ $file, ... ], \@args ] | ||||
320 | #------------------------------------------------------------------------ | ||||
321 | |||||
322 | sub insert { | ||||
323 | my ($class, $nameargs) = @_; | ||||
324 | my ($file, $args) = @$nameargs; | ||||
325 | $file = $class->filenames($file); | ||||
326 | return "$OUTPUT \$context->insert($file);"; | ||||
327 | } | ||||
328 | |||||
329 | |||||
330 | #------------------------------------------------------------------------ | ||||
331 | # include(\@nameargs) [% INCLUDE template foo = bar %] | ||||
332 | # # => [ [ $file, ... ], \@args ] | ||||
333 | #------------------------------------------------------------------------ | ||||
334 | |||||
335 | # spent 193µs (115+78) within Template::Directive::include which was called 8 times, avg 24µs/call:
# 8 times (115µs+78µs) by Template::Grammar::__ANON__[Parser.yp:118] at line 118 of Parser.yp, avg 24µs/call | ||||
336 | 8 | 11µs | my ($class, $nameargs) = @_; | ||
337 | 8 | 10µs | my ($file, $args) = @$nameargs; | ||
338 | 8 | 8µs | my $hash = shift @$args; | ||
339 | 8 | 35µs | 8 | 78µs | $file = $class->filenames($file); # spent 78µs making 8 calls to Template::Directive::filenames, avg 10µs/call |
340 | 8 | 9µs | $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; | ||
341 | 8 | 39µs | return "$OUTPUT \$context->include($file);"; | ||
342 | } | ||||
343 | |||||
344 | |||||
345 | #------------------------------------------------------------------------ | ||||
346 | # process(\@nameargs) [% PROCESS template foo = bar %] | ||||
347 | # # => [ [ $file, ... ], \@args ] | ||||
348 | #------------------------------------------------------------------------ | ||||
349 | |||||
350 | sub process { | ||||
351 | my ($class, $nameargs) = @_; | ||||
352 | my ($file, $args) = @$nameargs; | ||||
353 | my $hash = shift @$args; | ||||
354 | $file = $class->filenames($file); | ||||
355 | $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; | ||||
356 | return "$OUTPUT \$context->process($file);"; | ||||
357 | } | ||||
358 | |||||
359 | |||||
360 | #------------------------------------------------------------------------ | ||||
361 | # if($expr, $block, $else) [% IF foo < bar %] | ||||
362 | # ... | ||||
363 | # [% ELSE %] | ||||
364 | # ... | ||||
365 | # [% END %] | ||||
366 | #------------------------------------------------------------------------ | ||||
367 | |||||
368 | # spent 4.68ms within Template::Directive::if which was called 286 times, avg 16µs/call:
# 273 times (4.52ms+0s) by Template::Grammar::__ANON__[Parser.yp:141] at line 141 of Parser.yp, avg 17µs/call
# 12 times (162µs+0s) by Template::Grammar::__ANON__[Parser.yp:144] at line 144 of Parser.yp, avg 13µs/call
# once (6µs+0s) by Template::Grammar::__ANON__[Parser.yp:145] at line 145 of Parser.yp | ||||
369 | 286 | 543µs | my ($class, $expr, $block, $else) = @_; | ||
370 | 286 | 373µs | my @else = $else ? @$else : (); | ||
371 | 286 | 216µs | $else = pop @else; | ||
372 | 286 | 108µs | $block = pad($block, 1) if $PRETTY; | ||
373 | |||||
374 | 286 | 822µs | my $output = "if ($expr) {\n$block\n}\n"; | ||
375 | |||||
376 | 286 | 554µs | foreach my $elsif (@else) { | ||
377 | 4 | 6µs | ($expr, $block) = @$elsif; | ||
378 | 4 | 1µs | $block = pad($block, 1) if $PRETTY; | ||
379 | 4 | 15µs | $output .= "elsif ($expr) {\n$block\n}\n"; | ||
380 | } | ||||
381 | 286 | 158µs | if (defined $else) { | ||
382 | 93 | 25µs | $else = pad($else, 1) if $PRETTY; | ||
383 | 93 | 276µs | $output .= "else {\n$else\n}\n"; | ||
384 | } | ||||
385 | |||||
386 | 286 | 2.44ms | return $output; | ||
387 | } | ||||
388 | |||||
389 | |||||
390 | #------------------------------------------------------------------------ | ||||
391 | # foreach($target, $list, $args, $block) [% FOREACH x = [ foo bar ] %] | ||||
392 | # ... | ||||
393 | # [% END %] | ||||
394 | #------------------------------------------------------------------------ | ||||
395 | |||||
396 | # spent 1.40ms (1.12+281µs) within Template::Directive::foreach which was called 27 times, avg 52µs/call:
# 27 times (1.12ms+281µs) by Template::Grammar::__ANON__[Parser.yp:168] at line 168 of Parser.yp, avg 52µs/call | ||||
397 | 27 | 102µs | my ($class, $target, $list, $args, $block, $label) = @_; | ||
398 | 27 | 33µs | $args = shift @$args; | ||
399 | 27 | 51µs | $args = @$args ? ', { ' . join(', ', @$args) . ' }' : ''; | ||
400 | 27 | 12µs | $label ||= 'LOOP'; | ||
401 | |||||
402 | 27 | 27µs | my ($loop_save, $loop_set, $loop_restore, $setiter); | ||
403 | 27 | 91µs | if ($target) { | ||
404 | 27 | 186µs | 27 | 281µs | $loop_save = 'eval { $_tt_oldloop = ' . &ident($class, ["'loop'"]) . ' }'; # spent 281µs making 27 calls to Template::Directive::ident, avg 10µs/call |
405 | 27 | 39µs | $loop_set = "\$stash->{'$target'} = \$_tt_value"; | ||
406 | 27 | 27µs | $loop_restore = "\$stash->set('loop', \$_tt_oldloop)"; | ||
407 | } | ||||
408 | else { | ||||
409 | $loop_save = '$stash = $context->localise()'; | ||||
410 | # $loop_set = "\$stash->set('import', \$_tt_value) " | ||||
411 | # . "if ref \$value eq 'HASH'"; | ||||
412 | $loop_set = "\$stash->get(['import', [\$_tt_value]]) " | ||||
413 | . "if ref \$_tt_value eq 'HASH'"; | ||||
414 | $loop_restore = '$stash = $context->delocalise()'; | ||||
415 | } | ||||
416 | 27 | 19µs | $block = pad($block, 3) if $PRETTY; | ||
417 | |||||
418 | 27 | 484µs | return <<EOF; | ||
419 | |||||
420 | # FOREACH | ||||
421 | do { | ||||
422 | my (\$_tt_value, \$_tt_error, \$_tt_oldloop); | ||||
423 | my \$_tt_list = $list; | ||||
424 | |||||
425 | unless (UNIVERSAL::isa(\$_tt_list, 'Template::Iterator')) { | ||||
426 | \$_tt_list = Template::Config->iterator(\$_tt_list) | ||||
427 | || die \$Template::Config::ERROR, "\\n"; | ||||
428 | } | ||||
429 | |||||
430 | (\$_tt_value, \$_tt_error) = \$_tt_list->get_first(); | ||||
431 | $loop_save; | ||||
432 | \$stash->set('loop', \$_tt_list); | ||||
433 | eval { | ||||
434 | $label: while (! \$_tt_error) { | ||||
435 | $loop_set; | ||||
436 | $block; | ||||
437 | (\$_tt_value, \$_tt_error) = \$_tt_list->get_next(); | ||||
438 | } | ||||
439 | }; | ||||
440 | $loop_restore; | ||||
441 | die \$@ if \$@; | ||||
442 | \$_tt_error = 0 if \$_tt_error && \$_tt_error eq Template::Constants::STATUS_DONE; | ||||
443 | die \$_tt_error if \$_tt_error; | ||||
444 | }; | ||||
445 | EOF | ||||
446 | } | ||||
447 | |||||
448 | #------------------------------------------------------------------------ | ||||
449 | # next() [% NEXT %] | ||||
450 | # | ||||
451 | # Next iteration of a FOREACH loop (experimental) | ||||
452 | #------------------------------------------------------------------------ | ||||
453 | |||||
454 | sub next { | ||||
455 | my ($class, $label) = @_; | ||||
456 | $label ||= 'LOOP'; | ||||
457 | return <<EOF; | ||||
458 | (\$_tt_value, \$_tt_error) = \$_tt_list->get_next(); | ||||
459 | next $label; | ||||
460 | EOF | ||||
461 | } | ||||
462 | |||||
463 | |||||
464 | #------------------------------------------------------------------------ | ||||
465 | # wrapper(\@nameargs, $block) [% WRAPPER template foo = bar %] | ||||
466 | # # => [ [$file,...], \@args ] | ||||
467 | #------------------------------------------------------------------------ | ||||
468 | |||||
469 | sub wrapper { | ||||
470 | my ($class, $nameargs, $block) = @_; | ||||
471 | my ($file, $args) = @$nameargs; | ||||
472 | my $hash = shift @$args; | ||||
473 | |||||
474 | local $" = ', '; | ||||
475 | # print STDERR "wrapper([@$file], { @$hash })\n"; | ||||
476 | |||||
477 | return $class->multi_wrapper($file, $hash, $block) | ||||
478 | if @$file > 1; | ||||
479 | $file = shift @$file; | ||||
480 | |||||
481 | $block = pad($block, 1) if $PRETTY; | ||||
482 | push(@$hash, "'content'", '$output'); | ||||
483 | $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; | ||||
484 | |||||
485 | return <<EOF; | ||||
486 | |||||
487 | # WRAPPER | ||||
488 | $OUTPUT do { | ||||
489 | my \$output = ''; | ||||
490 | $block | ||||
491 | \$context->include($file); | ||||
492 | }; | ||||
493 | EOF | ||||
494 | } | ||||
495 | |||||
496 | |||||
497 | sub multi_wrapper { | ||||
498 | my ($class, $file, $hash, $block) = @_; | ||||
499 | $block = pad($block, 1) if $PRETTY; | ||||
500 | |||||
501 | push(@$hash, "'content'", '$output'); | ||||
502 | $hash = @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; | ||||
503 | |||||
504 | $file = join(', ', reverse @$file); | ||||
505 | # print STDERR "multi wrapper: $file\n"; | ||||
506 | |||||
507 | return <<EOF; | ||||
508 | |||||
509 | # WRAPPER | ||||
510 | $OUTPUT do { | ||||
511 | my \$output = ''; | ||||
512 | $block | ||||
513 | foreach ($file) { | ||||
514 | \$output = \$context->include(\$_$hash); | ||||
515 | } | ||||
516 | \$output; | ||||
517 | }; | ||||
518 | EOF | ||||
519 | } | ||||
520 | |||||
521 | |||||
522 | #------------------------------------------------------------------------ | ||||
523 | # while($expr, $block) [% WHILE x < 10 %] | ||||
524 | # ... | ||||
525 | # [% END %] | ||||
526 | #------------------------------------------------------------------------ | ||||
527 | |||||
528 | sub while { | ||||
529 | my ($class, $expr, $block, $label) = @_; | ||||
530 | $block = pad($block, 2) if $PRETTY; | ||||
531 | $label ||= 'LOOP'; | ||||
532 | |||||
533 | return <<EOF; | ||||
534 | |||||
535 | # WHILE | ||||
536 | do { | ||||
537 | my \$_tt_failsafe = $WHILE_MAX; | ||||
538 | $label: | ||||
539 | while (--\$_tt_failsafe && ($expr)) { | ||||
540 | $block | ||||
541 | } | ||||
542 | die "WHILE loop terminated (> $WHILE_MAX iterations)\\n" | ||||
543 | unless \$_tt_failsafe; | ||||
544 | }; | ||||
545 | EOF | ||||
546 | } | ||||
547 | |||||
548 | |||||
549 | #------------------------------------------------------------------------ | ||||
550 | # switch($expr, \@case) [% SWITCH %] | ||||
551 | # [% CASE foo %] | ||||
552 | # ... | ||||
553 | # [% END %] | ||||
554 | #------------------------------------------------------------------------ | ||||
555 | |||||
556 | sub switch { | ||||
557 | my ($class, $expr, $case) = @_; | ||||
558 | my @case = @$case; | ||||
559 | my ($match, $block, $default); | ||||
560 | my $caseblock = ''; | ||||
561 | |||||
562 | $default = pop @case; | ||||
563 | |||||
564 | foreach $case (@case) { | ||||
565 | $match = $case->[0]; | ||||
566 | $block = $case->[1]; | ||||
567 | $block = pad($block, 1) if $PRETTY; | ||||
568 | $caseblock .= <<EOF; | ||||
569 | \$_tt_match = $match; | ||||
570 | \$_tt_match = [ \$_tt_match ] unless ref \$_tt_match eq 'ARRAY'; | ||||
571 | if (grep(/^\\Q\$_tt_result\\E\$/, \@\$_tt_match)) { | ||||
572 | $block | ||||
573 | last SWITCH; | ||||
574 | } | ||||
575 | EOF | ||||
576 | } | ||||
577 | |||||
578 | $caseblock .= $default | ||||
579 | if defined $default; | ||||
580 | $caseblock = pad($caseblock, 2) if $PRETTY; | ||||
581 | |||||
582 | return <<EOF; | ||||
583 | |||||
584 | # SWITCH | ||||
585 | do { | ||||
586 | my \$_tt_result = $expr; | ||||
587 | my \$_tt_match; | ||||
588 | SWITCH: { | ||||
589 | $caseblock | ||||
590 | } | ||||
591 | }; | ||||
592 | EOF | ||||
593 | } | ||||
594 | |||||
595 | |||||
596 | #------------------------------------------------------------------------ | ||||
597 | # try($block, \@catch) [% TRY %] | ||||
598 | # ... | ||||
599 | # [% CATCH %] | ||||
600 | # ... | ||||
601 | # [% END %] | ||||
602 | #------------------------------------------------------------------------ | ||||
603 | |||||
604 | sub try { | ||||
605 | my ($class, $block, $catch) = @_; | ||||
606 | my @catch = @$catch; | ||||
607 | my ($match, $mblock, $default, $final, $n); | ||||
608 | my $catchblock = ''; | ||||
609 | my $handlers = []; | ||||
610 | |||||
611 | $block = pad($block, 2) if $PRETTY; | ||||
612 | $final = pop @catch; | ||||
613 | $final = "# FINAL\n" . ($final ? "$final\n" : '') | ||||
614 | . 'die $_tt_error if $_tt_error;' . "\n" . '$output;'; | ||||
615 | $final = pad($final, 1) if $PRETTY; | ||||
616 | |||||
617 | $n = 0; | ||||
618 | foreach $catch (@catch) { | ||||
619 | $match = $catch->[0] || do { | ||||
620 | $default ||= $catch->[1]; | ||||
621 | next; | ||||
622 | }; | ||||
623 | $mblock = $catch->[1]; | ||||
624 | $mblock = pad($mblock, 1) if $PRETTY; | ||||
625 | push(@$handlers, "'$match'"); | ||||
626 | $catchblock .= $n++ | ||||
627 | ? "elsif (\$_tt_handler eq '$match') {\n$mblock\n}\n" | ||||
628 | : "if (\$_tt_handler eq '$match') {\n$mblock\n}\n"; | ||||
629 | } | ||||
630 | $catchblock .= "\$_tt_error = 0;"; | ||||
631 | $catchblock = pad($catchblock, 3) if $PRETTY; | ||||
632 | if ($default) { | ||||
633 | $default = pad($default, 1) if $PRETTY; | ||||
634 | $default = "else {\n # DEFAULT\n$default\n \$_tt_error = '';\n}"; | ||||
635 | } | ||||
636 | else { | ||||
637 | $default = '# NO DEFAULT'; | ||||
638 | } | ||||
639 | $default = pad($default, 2) if $PRETTY; | ||||
640 | |||||
641 | $handlers = join(', ', @$handlers); | ||||
642 | return <<EOF; | ||||
643 | |||||
644 | # TRY | ||||
645 | $OUTPUT do { | ||||
646 | my \$output = ''; | ||||
647 | my (\$_tt_error, \$_tt_handler); | ||||
648 | eval { | ||||
649 | $block | ||||
650 | }; | ||||
651 | if (\$@) { | ||||
652 | \$_tt_error = \$context->catch(\$@, \\\$output); | ||||
653 | die \$_tt_error if \$_tt_error->type =~ /^return|stop\$/; | ||||
654 | \$stash->set('error', \$_tt_error); | ||||
655 | \$stash->set('e', \$_tt_error); | ||||
656 | if (defined (\$_tt_handler = \$_tt_error->select_handler($handlers))) { | ||||
657 | $catchblock | ||||
658 | } | ||||
659 | $default | ||||
660 | } | ||||
661 | $final | ||||
662 | }; | ||||
663 | EOF | ||||
664 | } | ||||
665 | |||||
666 | |||||
667 | #------------------------------------------------------------------------ | ||||
668 | # throw(\@nameargs) [% THROW foo "bar error" %] | ||||
669 | # # => [ [$type], \@args ] | ||||
670 | #------------------------------------------------------------------------ | ||||
671 | |||||
672 | sub throw { | ||||
673 | my ($class, $nameargs) = @_; | ||||
674 | my ($type, $args) = @$nameargs; | ||||
675 | my $hash = shift(@$args); | ||||
676 | my $info = shift(@$args); | ||||
677 | $type = shift @$type; # uses same parser production as INCLUDE | ||||
678 | # etc., which allow multiple names | ||||
679 | # e.g. INCLUDE foo+bar+baz | ||||
680 | |||||
681 | if (! $info) { | ||||
682 | $args = "$type, undef"; | ||||
683 | } | ||||
684 | elsif (@$hash || @$args) { | ||||
685 | local $" = ', '; | ||||
686 | my $i = 0; | ||||
687 | $args = "$type, { args => [ " | ||||
688 | . join(', ', $info, @$args) | ||||
689 | . ' ], ' | ||||
690 | . join(', ', | ||||
691 | (map { "'" . $i++ . "' => $_" } ($info, @$args)), | ||||
692 | @$hash) | ||||
693 | . ' }'; | ||||
694 | } | ||||
695 | else { | ||||
696 | $args = "$type, $info"; | ||||
697 | } | ||||
698 | |||||
699 | return "\$context->throw($args, \\\$output);"; | ||||
700 | } | ||||
701 | |||||
702 | |||||
703 | #------------------------------------------------------------------------ | ||||
704 | # clear() [% CLEAR %] | ||||
705 | # | ||||
706 | # NOTE: this is redundant, being hard-coded (for now) into Parser.yp | ||||
707 | #------------------------------------------------------------------------ | ||||
708 | |||||
709 | sub clear { | ||||
710 | return "\$output = '';"; | ||||
711 | } | ||||
712 | |||||
713 | #------------------------------------------------------------------------ | ||||
714 | # break() [% BREAK %] | ||||
715 | # | ||||
716 | # NOTE: this is redundant, being hard-coded (for now) into Parser.yp | ||||
717 | #------------------------------------------------------------------------ | ||||
718 | |||||
719 | sub OLD_break { | ||||
720 | return 'last LOOP;'; | ||||
721 | } | ||||
722 | |||||
723 | #------------------------------------------------------------------------ | ||||
724 | # return() [% RETURN %] | ||||
725 | #------------------------------------------------------------------------ | ||||
726 | |||||
727 | sub return { | ||||
728 | return "\$context->throw('return', '', \\\$output);"; | ||||
729 | } | ||||
730 | |||||
731 | #------------------------------------------------------------------------ | ||||
732 | # stop() [% STOP %] | ||||
733 | #------------------------------------------------------------------------ | ||||
734 | |||||
735 | sub stop { | ||||
736 | return "\$context->throw('stop', '', \\\$output);"; | ||||
737 | } | ||||
738 | |||||
739 | |||||
740 | #------------------------------------------------------------------------ | ||||
741 | # use(\@lnameargs) [% USE alias = plugin(args) %] | ||||
742 | # # => [ [$file, ...], \@args, $alias ] | ||||
743 | #------------------------------------------------------------------------ | ||||
744 | |||||
745 | sub use { | ||||
746 | my ($class, $lnameargs) = @_; | ||||
747 | my ($file, $args, $alias) = @$lnameargs; | ||||
748 | $file = shift @$file; # same production rule as INCLUDE | ||||
749 | $alias ||= $file; | ||||
750 | $args = &args($class, $args); | ||||
751 | $file .= ", $args" if $args; | ||||
752 | # my $set = &assign($class, $alias, '$plugin'); | ||||
753 | return "# USE\n" | ||||
754 | . "\$stash->set($alias,\n" | ||||
755 | . " \$context->plugin($file));"; | ||||
756 | } | ||||
757 | |||||
758 | #------------------------------------------------------------------------ | ||||
759 | # view(\@nameargs, $block) [% VIEW name args %] | ||||
760 | # # => [ [$file, ... ], \@args ] | ||||
761 | #------------------------------------------------------------------------ | ||||
762 | |||||
763 | sub view { | ||||
764 | my ($class, $nameargs, $block, $defblocks) = @_; | ||||
765 | my ($name, $args) = @$nameargs; | ||||
766 | my $hash = shift @$args; | ||||
767 | $name = shift @$name; # same production rule as INCLUDE | ||||
768 | $block = pad($block, 1) if $PRETTY; | ||||
769 | |||||
770 | if (%$defblocks) { | ||||
771 | $defblocks = join(",\n", map { "'$_' => $defblocks->{ $_ }" } | ||||
772 | keys %$defblocks); | ||||
773 | $defblocks = pad($defblocks, 1) if $PRETTY; | ||||
774 | $defblocks = "{\n$defblocks\n}"; | ||||
775 | push(@$hash, "'blocks'", $defblocks); | ||||
776 | } | ||||
777 | $hash = @$hash ? '{ ' . join(', ', @$hash) . ' }' : ''; | ||||
778 | |||||
779 | return <<EOF; | ||||
780 | # VIEW | ||||
781 | do { | ||||
782 | my \$output = ''; | ||||
783 | my \$_tt_oldv = \$stash->get('view'); | ||||
784 | my \$_tt_view = \$context->view($hash); | ||||
785 | \$stash->set($name, \$_tt_view); | ||||
786 | \$stash->set('view', \$_tt_view); | ||||
787 | |||||
788 | $block | ||||
789 | |||||
790 | \$stash->set('view', \$_tt_oldv); | ||||
791 | \$_tt_view->seal(); | ||||
792 | # \$output; # not used - commented out to avoid warning | ||||
793 | }; | ||||
794 | EOF | ||||
795 | } | ||||
796 | |||||
797 | |||||
798 | #------------------------------------------------------------------------ | ||||
799 | # perl($block) | ||||
800 | #------------------------------------------------------------------------ | ||||
801 | |||||
802 | sub perl { | ||||
803 | my ($class, $block) = @_; | ||||
804 | $block = pad($block, 1) if $PRETTY; | ||||
805 | |||||
806 | return <<EOF; | ||||
807 | |||||
808 | # PERL | ||||
809 | \$context->throw('perl', 'EVAL_PERL not set') | ||||
810 | unless \$context->eval_perl(); | ||||
811 | |||||
812 | $OUTPUT do { | ||||
813 | my \$output = "package Template::Perl;\\n"; | ||||
814 | |||||
815 | $block | ||||
816 | |||||
817 | local(\$Template::Perl::context) = \$context; | ||||
818 | local(\$Template::Perl::stash) = \$stash; | ||||
819 | |||||
820 | my \$_tt_result = ''; | ||||
821 | tie *Template::Perl::PERLOUT, 'Template::TieString', \\\$_tt_result; | ||||
822 | my \$_tt_save_stdout = select *Template::Perl::PERLOUT; | ||||
823 | |||||
824 | eval \$output; | ||||
825 | select \$_tt_save_stdout; | ||||
826 | \$context->throw(\$@) if \$@; | ||||
827 | \$_tt_result; | ||||
828 | }; | ||||
829 | EOF | ||||
830 | } | ||||
831 | |||||
832 | |||||
833 | #------------------------------------------------------------------------ | ||||
834 | # no_perl() | ||||
835 | #------------------------------------------------------------------------ | ||||
836 | |||||
837 | sub no_perl { | ||||
838 | my $class = shift; | ||||
839 | return "\$context->throw('perl', 'EVAL_PERL not set');"; | ||||
840 | } | ||||
841 | |||||
842 | |||||
843 | #------------------------------------------------------------------------ | ||||
844 | # rawperl($block) | ||||
845 | # | ||||
846 | # NOTE: perhaps test context EVAL_PERL switch at compile time rather than | ||||
847 | # runtime? | ||||
848 | #------------------------------------------------------------------------ | ||||
849 | |||||
850 | sub rawperl { | ||||
851 | my ($class, $block, $line) = @_; | ||||
852 | for ($block) { | ||||
853 | s/^\n+//; | ||||
854 | s/\n+$//; | ||||
855 | } | ||||
856 | $block = pad($block, 1) if $PRETTY; | ||||
857 | $line = $line ? " (starting line $line)" : ''; | ||||
858 | |||||
859 | return <<EOF; | ||||
860 | # RAWPERL | ||||
861 | #line 1 "RAWPERL block$line" | ||||
862 | $block | ||||
863 | EOF | ||||
864 | } | ||||
865 | |||||
- - | |||||
868 | #------------------------------------------------------------------------ | ||||
869 | # filter() | ||||
870 | #------------------------------------------------------------------------ | ||||
871 | |||||
872 | # spent 2.06ms (1.60+460µs) within Template::Directive::filter which was called 74 times, avg 28µs/call:
# 74 times (1.60ms+460µs) by Template::Grammar::__ANON__[Parser.yp:229] at line 229 of Parser.yp, avg 28µs/call | ||||
873 | 74 | 216µs | my ($class, $lnameargs, $block) = @_; | ||
874 | 74 | 88µs | my ($name, $args, $alias) = @$lnameargs; | ||
875 | 74 | 154µs | $name = shift @$name; | ||
876 | 74 | 272µs | 74 | 460µs | $args = &args($class, $args); # spent 460µs making 74 calls to Template::Directive::args, avg 6µs/call |
877 | 74 | 32µs | $args = $args ? "$args, $alias" : ", undef, $alias" | ||
878 | if $alias; | ||||
879 | 74 | 26µs | $name .= ", $args" if $args; | ||
880 | 74 | 33µs | $block = pad($block, 1) if $PRETTY; | ||
881 | |||||
882 | 74 | 637µs | return <<EOF; | ||
883 | |||||
884 | # FILTER | ||||
885 | $OUTPUT do { | ||||
886 | my \$output = ''; | ||||
887 | my \$_tt_filter = \$context->filter($name) | ||||
888 | || \$context->throw(\$context->error); | ||||
889 | |||||
890 | $block | ||||
891 | |||||
892 | &\$_tt_filter(\$output); | ||||
893 | }; | ||||
894 | EOF | ||||
895 | } | ||||
896 | |||||
897 | |||||
898 | #------------------------------------------------------------------------ | ||||
899 | # capture($name, $block) | ||||
900 | #------------------------------------------------------------------------ | ||||
901 | |||||
902 | sub capture { | ||||
903 | my ($class, $name, $block) = @_; | ||||
904 | |||||
905 | if (ref $name) { | ||||
906 | if (scalar @$name == 2 && ! $name->[1]) { | ||||
907 | $name = $name->[0]; | ||||
908 | } | ||||
909 | else { | ||||
910 | $name = '[' . join(', ', @$name) . ']'; | ||||
911 | } | ||||
912 | } | ||||
913 | $block = pad($block, 1) if $PRETTY; | ||||
914 | |||||
915 | return <<EOF; | ||||
916 | |||||
917 | # CAPTURE | ||||
918 | \$stash->set($name, do { | ||||
919 | my \$output = ''; | ||||
920 | $block | ||||
921 | \$output; | ||||
922 | }); | ||||
923 | EOF | ||||
924 | |||||
925 | } | ||||
926 | |||||
927 | |||||
928 | #------------------------------------------------------------------------ | ||||
929 | # macro($name, $block, \@args) | ||||
930 | #------------------------------------------------------------------------ | ||||
931 | |||||
932 | sub macro { | ||||
933 | my ($class, $ident, $block, $args) = @_; | ||||
934 | $block = pad($block, 2) if $PRETTY; | ||||
935 | |||||
936 | if ($args) { | ||||
937 | my $nargs = scalar @$args; | ||||
938 | $args = join(', ', map { "'$_'" } @$args); | ||||
939 | $args = $nargs > 1 | ||||
940 | ? "\@_tt_args{ $args } = splice(\@_, 0, $nargs)" | ||||
941 | : "\$_tt_args{ $args } = shift"; | ||||
942 | |||||
943 | return <<EOF; | ||||
944 | |||||
945 | # MACRO | ||||
946 | \$stash->set('$ident', sub { | ||||
947 | my \$output = ''; | ||||
948 | my (%_tt_args, \$_tt_params); | ||||
949 | $args; | ||||
950 | \$_tt_params = shift; | ||||
951 | \$_tt_params = { } unless ref(\$_tt_params) eq 'HASH'; | ||||
952 | \$_tt_params = { \%_tt_args, %\$_tt_params }; | ||||
953 | |||||
954 | my \$stash = \$context->localise(\$_tt_params); | ||||
955 | eval { | ||||
956 | $block | ||||
957 | }; | ||||
958 | \$stash = \$context->delocalise(); | ||||
959 | die \$@ if \$@; | ||||
960 | return \$output; | ||||
961 | }); | ||||
962 | EOF | ||||
963 | |||||
964 | } | ||||
965 | else { | ||||
966 | return <<EOF; | ||||
967 | |||||
968 | # MACRO | ||||
969 | \$stash->set('$ident', sub { | ||||
970 | my \$_tt_params = \$_[0] if ref(\$_[0]) eq 'HASH'; | ||||
971 | my \$output = ''; | ||||
972 | |||||
973 | my \$stash = \$context->localise(\$_tt_params); | ||||
974 | eval { | ||||
975 | $block | ||||
976 | }; | ||||
977 | \$stash = \$context->delocalise(); | ||||
978 | die \$@ if \$@; | ||||
979 | return \$output; | ||||
980 | }); | ||||
981 | EOF | ||||
982 | } | ||||
983 | } | ||||
984 | |||||
985 | |||||
986 | sub debug { | ||||
987 | my ($class, $nameargs) = @_; | ||||
988 | my ($file, $args) = @$nameargs; | ||||
989 | my $hash = shift @$args; | ||||
990 | $args = join(', ', @$file, @$args); | ||||
991 | $args .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : ''; | ||||
992 | return "$OUTPUT \$context->debugging($args); ## DEBUG ##"; | ||||
993 | } | ||||
994 | |||||
995 | |||||
996 | 1 | 6µs | 1; | ||
997 | |||||
998 | __END__ | ||||
# spent 698µs (167+530) within Template::Directive::CORE:match which was called 8 times, avg 87µs/call:
# 8 times (167µs+530µs) by Template::Directive::template at line 70, avg 87µs/call | |||||
sub Template::Directive::CORE:subst; # opcode | |||||
# spent 4.81ms within Template::Directive::CORE:substcont which was called 2526 times, avg 2µs/call:
# 2526 times (4.81ms+0s) by Template::Directive::text at line 149, avg 2µs/call |