line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Template::Parser::CET; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
4
|
|
|
|
|
|
|
# Copyright 2007 - Paul Seamons # |
5
|
|
|
|
|
|
|
# Distributed under the Perl Artistic License without warranty # |
6
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
7
|
|
|
|
|
|
|
|
8
|
5
|
|
|
5
|
|
132515
|
use vars qw($VERSION $TEMP_VARNAME $ORIG_CONFIG_CLASS $NO_LOAD_EXTRA_VMETHODS); |
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
443
|
|
9
|
5
|
|
|
5
|
|
34
|
use strict; |
|
5
|
|
|
|
|
11
|
|
|
5
|
|
|
|
|
199
|
|
10
|
5
|
|
|
5
|
|
36
|
use warnings; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
178
|
|
11
|
5
|
|
|
5
|
|
27
|
use base qw(Template::Alloy); |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
5353
|
|
12
|
|
|
|
|
|
|
|
13
|
5
|
|
|
5
|
|
159590
|
use Template::Alloy 1.008; |
|
5
|
|
|
|
|
149
|
|
|
5
|
|
|
|
|
39
|
|
14
|
5
|
|
|
5
|
|
163
|
use Template::Alloy::Operator qw($OP_ASSIGN $OP_DISPATCH); |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
712
|
|
15
|
5
|
|
|
5
|
|
5434
|
use Template::Directive; |
|
5
|
|
|
|
|
26968
|
|
|
5
|
|
|
|
|
183
|
|
16
|
5
|
|
|
5
|
|
48
|
use Template::Constants; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
273
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
BEGIN { |
19
|
5
|
|
|
5
|
|
13
|
$VERSION = '0.05'; |
20
|
|
|
|
|
|
|
|
21
|
5
|
|
|
|
|
44755
|
$TEMP_VARNAME = 'template_parser_cet_temp_varname'; |
22
|
|
|
|
|
|
|
}; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
sub new { |
27
|
698
|
|
|
698
|
1
|
285187
|
my $class = shift; |
28
|
698
|
|
|
|
|
2936
|
my $self = $class->SUPER::new(@_); |
29
|
|
|
|
|
|
|
|
30
|
698
|
|
50
|
|
|
11508
|
$self->{'FACTORY'} ||= 'Template::Directive'; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# This debug section taken nearly verbatim from Template::Parser::new |
33
|
|
|
|
|
|
|
# DEBUG config item can be a bitmask |
34
|
698
|
50
|
|
|
|
1899
|
if (defined (my $debug = $self->{'DEBUG'})) { |
35
|
0
|
|
|
|
|
0
|
$self->{ DEBUG } = $debug & ( Template::Constants::DEBUG_PARSER |
36
|
|
|
|
|
|
|
| Template::Constants::DEBUG_FLAGS ); |
37
|
0
|
|
|
|
|
0
|
$self->{ DEBUG_DIRS } = $debug & Template::Constants::DEBUG_DIRS; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# This factory section is taken nearly verbatim from Template::Parser::new |
41
|
698
|
50
|
|
|
|
1595
|
if ($self->{'NAMESPACE'}) { |
42
|
0
|
|
|
|
|
0
|
my $fclass = $self->{'FACTORY'}; |
43
|
0
|
|
0
|
|
|
0
|
$self->{'FACTORY'} = $fclass->new(NAMESPACE => $self->{'NAMESPACE'} ) |
44
|
|
|
|
|
|
|
|| return $class->error($fclass->error()); |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
698
|
|
|
|
|
1731
|
return $self; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
51
|
|
|
|
|
|
|
### methods for installing |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub activate { |
54
|
7
|
|
|
7
|
0
|
1574
|
require Template::Config; |
55
|
7
|
50
|
33
|
|
|
40
|
if (! $ORIG_CONFIG_CLASS || $ORIG_CONFIG_CLASS ne $Template::Config::PARSER) { |
56
|
7
|
|
|
|
|
17
|
$ORIG_CONFIG_CLASS = $Template::Config::PARSER; |
57
|
7
|
|
|
|
|
16
|
$Template::Config::PARSER = __PACKAGE__; |
58
|
|
|
|
|
|
|
} |
59
|
7
|
|
|
|
|
46
|
1; |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
sub deactivate { |
63
|
3
|
50
|
|
3
|
0
|
865
|
if ($ORIG_CONFIG_CLASS) { |
64
|
3
|
|
|
|
|
6
|
$Template::Config::PARSER = $ORIG_CONFIG_CLASS; |
65
|
3
|
|
|
|
|
7
|
$ORIG_CONFIG_CLASS = undef; |
66
|
|
|
|
|
|
|
} |
67
|
3
|
|
|
|
|
12
|
1; |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
sub import { |
71
|
6
|
|
|
6
|
|
525
|
my ($class, @args) = @_; |
72
|
6
|
50
|
|
|
|
35
|
push @args, 1 if @args % 2; |
73
|
6
|
|
|
|
|
18
|
my %args = @args; |
74
|
6
|
100
|
|
|
|
25
|
$class->activate if $args{'activate'}; |
75
|
6
|
50
|
|
|
|
24
|
$class->deactivate if $args{'deactivate'}; |
76
|
6
|
|
|
|
|
229
|
1; |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
80
|
|
|
|
|
|
|
### parse the document and return a valid compiled Template::Document |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub parse { |
83
|
735
|
|
|
735
|
1
|
89479
|
my ($self, $text, $info) = @_; |
84
|
735
|
|
|
|
|
820
|
my ($tokens, $block); |
85
|
|
|
|
|
|
|
|
86
|
735
|
|
|
|
|
832
|
eval { require Template::Stash }; |
|
735
|
|
|
|
|
3783
|
|
87
|
735
|
|
|
|
|
1107
|
local $Template::Alloy::QR_PRIVATE = $Template::Stash::PRIVATE; |
88
|
735
|
50
|
50
|
|
|
4331
|
local $self->{'_debug'} = defined($info->{'DEBUG'}) ? $info->{'DEBUG'} : $self->{'DEBUG_DIRS'} || undef; |
89
|
735
|
|
|
|
|
1526
|
local $self->{'DEFBLOCK'} = {}; |
90
|
735
|
|
|
|
|
1585
|
local $self->{'METADATA'} = []; |
91
|
735
|
|
|
|
|
3356
|
local $self->{'_component'} = { |
92
|
|
|
|
|
|
|
_content => \$text, |
93
|
|
|
|
|
|
|
name => $info->{'name'}, |
94
|
|
|
|
|
|
|
modtime => $info->{'time'}, |
95
|
|
|
|
|
|
|
}; |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
### parse to the AST |
98
|
735
|
|
|
|
|
1040
|
my $tree = eval { $self->parse_tree(\$text) }; # errors die |
|
735
|
|
|
|
|
2550
|
|
99
|
735
|
100
|
|
|
|
382014
|
if (! $tree) { |
100
|
19
|
|
|
|
|
29
|
my $err = $@; |
101
|
19
|
50
|
33
|
|
|
141
|
$err->doc($self->{'_component'}) if UNIVERSAL::can($err, 'doc') && ! $err->doc; |
102
|
19
|
|
|
|
|
532
|
die $err; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
### take the AST to the doc |
106
|
716
|
|
|
|
|
2157
|
my $doc = $self->{'FACTORY'}->template($self->compile_tree($tree)); |
107
|
|
|
|
|
|
|
# print $doc; |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
return { |
110
|
714
|
|
|
|
|
7621
|
BLOCK => $doc, |
111
|
|
|
|
|
|
|
DEFBLOCKS => $self->{'DEFBLOCK'}, |
112
|
714
|
|
|
|
|
11043
|
METADATA => { @{ $self->{'METADATA'} } }, |
113
|
|
|
|
|
|
|
}; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
### takes a tree of DIRECTIVES |
119
|
|
|
|
|
|
|
### and returns a TT block |
120
|
|
|
|
|
|
|
sub compile_tree { |
121
|
837
|
|
|
837
|
0
|
1395
|
my ($self, $tree) = @_; |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# node contains (0: DIRECTIVE, |
124
|
|
|
|
|
|
|
# 1: start_index, |
125
|
|
|
|
|
|
|
# 2: end_index, |
126
|
|
|
|
|
|
|
# 3: parsed tag details, |
127
|
|
|
|
|
|
|
# 4: sub tree for block types |
128
|
|
|
|
|
|
|
# 5: continuation sub trees for sub continuation block types (elsif, else, etc) |
129
|
|
|
|
|
|
|
# 6: flag to capture next directive |
130
|
837
|
|
|
|
|
1006
|
my @doc; |
131
|
837
|
|
|
|
|
1454
|
for my $node (@$tree) { |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
# text nodes are just the bare text |
134
|
1392
|
100
|
|
|
|
3517
|
if (! ref $node) { |
135
|
298
|
|
|
|
|
1268
|
my $result = $self->{'FACTORY'}->textblock($node); |
136
|
298
|
50
|
|
|
|
5331
|
push @doc, $result if defined $result; |
137
|
298
|
|
|
|
|
839
|
next; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
# add debug info |
141
|
1094
|
50
|
|
|
|
2470
|
if ($self->{'_debug'}) { |
142
|
0
|
|
|
|
|
0
|
my $info = $self->node_info($node); |
143
|
0
|
|
|
|
|
0
|
my ($file, $line, $text) = @{ $info }{qw(file line text) }; |
|
0
|
|
|
|
|
0
|
|
144
|
0
|
|
|
|
|
0
|
s/([\'\\])/\\$1/g for $file, $text; |
145
|
0
|
|
|
|
|
0
|
my $result = $self->{'FACTORY'}->debug([["'msg'"],[["file => '$file'", "line => $line", "text => '$text'"]]]); |
146
|
0
|
0
|
|
|
|
0
|
push @doc, $result if defined $result; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
# get method to call |
150
|
1094
|
|
|
|
|
1701
|
my $directive = $node->[0]; |
151
|
1094
|
50
|
|
|
|
2232
|
$directive = 'FILTER' if $directive eq '|'; |
152
|
1094
|
50
|
|
|
|
2181
|
next if $directive eq '#'; |
153
|
1094
|
|
|
|
|
1873
|
my $method = "compile_$directive"; |
154
|
1094
|
|
|
|
|
3412
|
my $result = $self->$method($node->[3], $node); |
155
|
1092
|
100
|
|
|
|
15931
|
push @doc, $result if defined $result; |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
|
158
|
835
|
|
|
|
|
3297
|
return $self->{'FACTORY'}->block(\@doc); |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
### take arguments parsed in parse_args({named_at_front => 1}) |
164
|
|
|
|
|
|
|
### and turn them into normal TT2 style args |
165
|
|
|
|
|
|
|
sub compile_named_args { |
166
|
25
|
|
|
25
|
0
|
48
|
my $self = shift; |
167
|
25
|
|
|
|
|
48
|
my $args = shift; |
168
|
25
|
|
|
|
|
57
|
my ($named, @positional) = @$args; |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
# [[undef, '{}', 'key1', 'val1', 'key2', 'val2'], 0] |
171
|
25
|
|
|
|
|
31
|
my @named; |
172
|
25
|
|
|
|
|
43
|
$named = $named->[0]; |
173
|
25
|
|
|
|
|
57
|
my (undef, $op, @the_rest) = @$named; |
174
|
25
|
|
|
|
|
69
|
while (@the_rest) { |
175
|
4
|
|
|
|
|
10
|
my $key = shift @the_rest; |
176
|
4
|
50
|
|
|
|
19
|
my $val = @the_rest ? $self->compile_expr(shift @the_rest) : 'undef'; |
177
|
4
|
0
|
33
|
|
|
19
|
$key = $key->[0] if ref($key) && @$key == 2 && ! ref $key->[0]; # simple keys can be set in place |
|
|
|
33
|
|
|
|
|
178
|
4
|
50
|
|
|
|
11
|
if (! ref $key) { |
179
|
4
|
|
|
|
|
11
|
$key = $self->compile_expr($key); |
180
|
4
|
|
|
|
|
21
|
push @named, "$key => $val"; |
181
|
|
|
|
|
|
|
} else { |
182
|
|
|
|
|
|
|
### this really is the way TT does it - pseudo assignment into a hash |
183
|
|
|
|
|
|
|
### with a key that gets thrown away - but "getting" the value assigns into the stash |
184
|
|
|
|
|
|
|
### scary and gross |
185
|
0
|
|
|
|
|
0
|
push @named, "'_' => ".$self->compile_expr($key, $val); |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
|
189
|
25
|
|
|
|
|
61
|
return [\@named, (map { $self->compile_expr($_) } @positional)]; |
|
25
|
|
|
|
|
71
|
|
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
### takes variables or expressions and translates them |
193
|
|
|
|
|
|
|
### into the language that compiled TT templates understand |
194
|
|
|
|
|
|
|
### it will recurse as deep as the expression is deep |
195
|
|
|
|
|
|
|
### foo : 'foo' |
196
|
|
|
|
|
|
|
### ['foo', 0] : $stash->get('foo') |
197
|
|
|
|
|
|
|
### ['foo', 0] = ['bar', 0] : $stash->set('foo', $stash->get('bar')) |
198
|
|
|
|
|
|
|
### [[undef, '+', 1, 2], 0] : do { no warnings; 1 + 2 } |
199
|
|
|
|
|
|
|
sub compile_expr { |
200
|
2175
|
|
|
2175
|
0
|
4809
|
my ($self, $var, $val, $default) = @_; |
201
|
2175
|
|
|
|
|
2885
|
my $ARGS = {}; |
202
|
2175
|
|
|
|
|
2659
|
my $i = 0; |
203
|
2175
|
|
|
|
|
3374
|
my $return_ref = delete $self->{'_return_ref_ident'}; # set in compile_operator |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
### return literals |
206
|
2175
|
100
|
|
|
|
4551
|
if (! ref $var) { |
207
|
829
|
50
|
|
|
|
1820
|
if ($val) { # allow for bare literal setting [% 'foo' = 'bar' %] |
208
|
0
|
|
|
|
|
0
|
$var = [$var, 0]; |
209
|
|
|
|
|
|
|
} else { |
210
|
829
|
100
|
|
|
|
4431
|
return $var if $var =~ /^-?[1-9]\d{0,13}(?:|\.0|\.\d{0,13}[1-9])$/; # return unquoted numbers if it is simple |
211
|
404
|
|
|
|
|
544
|
$var =~ s/\'/\\\'/g; |
212
|
404
|
|
|
|
|
2301
|
return "'$var'"; # return quoted items - if they are simple |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
### determine the top level of this particular variable access |
217
|
1346
|
|
|
|
|
1374
|
my @ident; |
218
|
1346
|
|
|
|
|
2206
|
my $name = $var->[$i++]; |
219
|
1346
|
|
|
|
|
1689
|
my $args = $var->[$i++]; |
220
|
1346
|
|
|
|
|
1757
|
my $use_temp_varname; |
221
|
1346
|
100
|
|
|
|
2875
|
if (ref $name) { |
|
|
50
|
|
|
|
|
|
222
|
429
|
100
|
|
|
|
1070
|
if (! defined $name->[0]) { # operator |
223
|
384
|
|
|
|
|
1032
|
my $op_val = '('. $self->compile_operator($name) .')'; |
224
|
384
|
100
|
|
|
|
2780
|
return $op_val if $i >= @$var; |
225
|
51
|
|
|
|
|
426
|
$use_temp_varname = "do {\n ".$self->{'FACTORY'}->assign(["'$TEMP_VARNAME'", 0], $op_val).";\n "; |
226
|
51
|
|
|
|
|
728
|
push @ident, "'$TEMP_VARNAME'"; |
227
|
|
|
|
|
|
|
} else { # a named variable access (ie via $name.foo) |
228
|
45
|
|
|
|
|
92
|
push @ident, $self->compile_expr($name); |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
} elsif (defined $name) { |
231
|
917
|
50
|
|
|
|
1627
|
if ($ARGS->{'is_namespace_during_compile'}) { |
232
|
|
|
|
|
|
|
#$ref = $self->{'NAMESPACE'}->{$name}; |
233
|
|
|
|
|
|
|
} else { |
234
|
917
|
|
|
|
|
1300
|
$name =~ s/\'/\\\'/g; |
235
|
917
|
|
|
|
|
2317
|
push @ident, "'$name'"; |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
} else { |
238
|
0
|
|
|
|
|
0
|
return ''; |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
### add args |
242
|
1013
|
100
|
|
|
|
2400
|
if (! $args) { |
243
|
989
|
|
|
|
|
1212
|
push @ident, 0; |
244
|
|
|
|
|
|
|
} else { |
245
|
24
|
|
|
|
|
67
|
push @ident, ("[" . join(",\n", map { $self->compile_expr($_) } @$args) . "]"); |
|
24
|
|
|
|
|
68
|
|
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
### now decent through the other levels |
249
|
1013
|
|
|
|
|
2456
|
while ($i < @$var) { |
250
|
|
|
|
|
|
|
### descend one chained level |
251
|
491
|
50
|
|
|
|
1359
|
my $was_dot_call = $ARGS->{'no_dots'} ? 1 : $var->[$i++] eq '.'; |
252
|
491
|
|
|
|
|
924
|
$name = $var->[$i++]; |
253
|
491
|
|
|
|
|
679
|
$args = $var->[$i++]; |
254
|
|
|
|
|
|
|
|
255
|
491
|
100
|
|
|
|
787
|
if ($was_dot_call) { |
256
|
438
|
100
|
|
|
|
978
|
if (ref $name) { |
|
|
50
|
|
|
|
|
|
257
|
10
|
50
|
|
|
|
22
|
if (! defined $name->[0]) { # operator |
258
|
0
|
|
|
|
|
0
|
push @ident, '('. $self->compile_operator($name) .')'; |
259
|
|
|
|
|
|
|
} else { # a named variable access (ie via $name.foo) |
260
|
10
|
|
|
|
|
25
|
push @ident, $self->compile_expr($name); |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
} elsif (defined $name) { |
263
|
428
|
50
|
|
|
|
696
|
if ($ARGS->{'is_namespace_during_compile'}) { |
264
|
|
|
|
|
|
|
#$ref = $self->{'NAMESPACE'}->{$name}; |
265
|
|
|
|
|
|
|
} else { |
266
|
428
|
|
|
|
|
564
|
$name =~ s/\'/\\\'/g; |
267
|
428
|
|
|
|
|
927
|
push @ident, "'$name'"; |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
} else { |
270
|
0
|
|
|
|
|
0
|
return ''; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
438
|
100
|
|
|
|
864
|
if (! $args) { |
274
|
328
|
|
|
|
|
1032
|
push @ident, 0; |
275
|
|
|
|
|
|
|
} else { |
276
|
110
|
|
|
|
|
213
|
push @ident, ("[" . join(",\n", map { $self->compile_expr($_) } @$args) . "]"); |
|
156
|
|
|
|
|
341
|
|
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
# chained filter access |
280
|
|
|
|
|
|
|
} else { |
281
|
|
|
|
|
|
|
# resolve and cleanup the name |
282
|
53
|
100
|
|
|
|
173
|
if (ref $name) { |
|
|
50
|
|
|
|
|
|
283
|
2
|
50
|
|
|
|
7
|
if (! defined $name->[0]) { # operator |
284
|
0
|
|
|
|
|
0
|
$name = '('. $self->compile_operator($name) .')'; |
285
|
|
|
|
|
|
|
} else { # a named variable access (ie via $name.foo) |
286
|
2
|
|
|
|
|
7
|
$name = $self->compile_expr($name); |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
} elsif (defined $name) { |
289
|
51
|
50
|
|
|
|
106
|
if ($ARGS->{'is_namespace_during_compile'}) { |
290
|
|
|
|
|
|
|
#$ref = $self->{'NAMESPACE'}->{$name}; |
291
|
|
|
|
|
|
|
} else { |
292
|
51
|
|
|
|
|
95
|
$name =~ s/\'/\\\'/g; |
293
|
51
|
|
|
|
|
105
|
$name = "'$name'"; |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
} else { |
296
|
0
|
|
|
|
|
0
|
return ''; |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
# get the ident to operate on |
300
|
53
|
|
|
|
|
120
|
my $ident; |
301
|
53
|
100
|
|
|
|
105
|
if ($use_temp_varname) { |
302
|
23
|
|
|
|
|
316
|
$ident = $use_temp_varname |
303
|
|
|
|
|
|
|
."my \$val = ".$self->{'FACTORY'}->ident(\@ident).";\n " |
304
|
|
|
|
|
|
|
.$self->{'FACTORY'}->assign(["'$TEMP_VARNAME'", 0], 'undef').";\n " |
305
|
|
|
|
|
|
|
."\$val; # return of the do\n }"; |
306
|
|
|
|
|
|
|
} else { |
307
|
30
|
|
|
|
|
151
|
$ident = $self->{'FACTORY'}->ident(\@ident); |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
# get args ready |
311
|
53
|
100
|
|
|
|
1112
|
my $filter_args = $args ? [[], map {$self->compile_expr($_)} @$args] : [[]]; |
|
6
|
|
|
|
|
18
|
|
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
# return the value that is able to run the filter |
314
|
53
|
|
|
|
|
127
|
my $block = "\$output = $ident;"; |
315
|
53
|
|
|
|
|
284
|
my $filt_val = "do { my \$output = '';\n". $self->{'FACTORY'}->filter([[$name], $filter_args], $block) ." \$output;\n }"; |
316
|
53
|
|
|
|
|
1222
|
$use_temp_varname = "do {\n ".$self->{'FACTORY'}->assign(["'$TEMP_VARNAME'", 0], $filt_val).";\n "; |
317
|
|
|
|
|
|
|
|
318
|
53
|
|
|
|
|
807
|
@ident = ("'$TEMP_VARNAME'", 0); |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
# handle captures |
323
|
1013
|
100
|
|
|
|
3908
|
if ($self->{'_return_capture_ident'}) { |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
324
|
2
|
50
|
|
|
|
8
|
die "Can't capture to a variable with filters (@ident)" if $use_temp_varname; |
325
|
2
|
50
|
|
|
|
8
|
die "Can't capture to a variable with a set value" if $val; |
326
|
2
|
|
|
|
|
10
|
return \@ident; |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
# handle refence getting |
329
|
|
|
|
|
|
|
} elsif ($return_ref) { |
330
|
0
|
0
|
|
|
|
0
|
die "Can't get reference to a variable with filters (@ident)" if $use_temp_varname; |
331
|
0
|
0
|
|
|
|
0
|
die "Can't get reference to a variable with a set value" if $val; |
332
|
0
|
|
|
|
|
0
|
return $self->{'FACTORY'}->identref(\@ident); |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
# handle setting values |
335
|
|
|
|
|
|
|
} elsif ($val) { |
336
|
197
|
|
|
|
|
1390
|
return $self->{'FACTORY'}->assign(\@ident, $val, $default); |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
# handle inline filters |
339
|
|
|
|
|
|
|
} elsif ($use_temp_varname) { |
340
|
81
|
|
|
|
|
417
|
return $use_temp_varname |
341
|
|
|
|
|
|
|
."my \$val = ".$self->{'FACTORY'}->ident(\@ident).";\n " |
342
|
|
|
|
|
|
|
.$self->{'FACTORY'}->assign(["'$TEMP_VARNAME'", 0], 'undef').";\n " |
343
|
|
|
|
|
|
|
."\$val; # return of the do\n }"; |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
# finally - normal getting |
346
|
|
|
|
|
|
|
} else { |
347
|
733
|
|
|
|
|
3103
|
return $self->{'FACTORY'}->ident(\@ident); |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
} |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
### plays operators |
352
|
|
|
|
|
|
|
### [[undef, '+', 1, 2], 0] : do { no warnings; 1 + 2 } |
353
|
|
|
|
|
|
|
### unfortunately we had to provide a lot of perl |
354
|
|
|
|
|
|
|
### here ourselves which means that Jemplate can't |
355
|
|
|
|
|
|
|
### use this parser directly without overriding this method |
356
|
|
|
|
|
|
|
sub compile_operator { |
357
|
384
|
|
|
384
|
0
|
496
|
my $self = shift; |
358
|
384
|
|
|
|
|
448
|
my $args = shift; |
359
|
384
|
|
|
|
|
929
|
my (undef, $op, @the_rest) = @$args; |
360
|
384
|
|
|
|
|
613
|
$op = lc $op; |
361
|
|
|
|
|
|
|
|
362
|
384
|
50
|
|
|
|
1181
|
$op = ($op eq 'mod') ? '%' |
|
|
50
|
|
|
|
|
|
363
|
|
|
|
|
|
|
: ($op eq 'pow') ? '**' |
364
|
|
|
|
|
|
|
: $op; |
365
|
|
|
|
|
|
|
|
366
|
384
|
100
|
100
|
|
|
4437
|
if ($op eq '{}') { |
|
|
100
|
66
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
367
|
30
|
100
|
|
|
|
81
|
return '{}' if ! @the_rest; |
368
|
29
|
|
|
|
|
52
|
my $out = "{\n"; |
369
|
29
|
|
|
|
|
77
|
while (@the_rest) { |
370
|
34
|
|
|
|
|
91
|
my $key = $self->compile_expr(shift @the_rest); |
371
|
34
|
50
|
|
|
|
183
|
my $val = @the_rest ? $self->compile_expr(shift @the_rest) : 'undef'; |
372
|
34
|
|
|
|
|
186
|
$out .= " $key => $val,\n"; |
373
|
|
|
|
|
|
|
} |
374
|
29
|
|
|
|
|
37
|
$out .= "}"; |
375
|
29
|
|
|
|
|
93
|
return $out; |
376
|
|
|
|
|
|
|
} elsif ($op eq '[]') { |
377
|
43
|
|
|
|
|
106
|
return "[".join(",\n ", (map { $self->compile_expr($_) } @the_rest))."]"; |
|
59
|
|
|
|
|
164
|
|
378
|
|
|
|
|
|
|
} elsif ($op eq '~' || $op eq '_') { |
379
|
42
|
|
|
|
|
72
|
return "(''.". join(".\n ", map { $self->compile_expr($_) } @the_rest).")"; |
|
57
|
|
|
|
|
181
|
|
380
|
|
|
|
|
|
|
} elsif ($op eq '=') { |
381
|
16
|
|
|
|
|
38
|
return $self->compile_expr($the_rest[0], $self->compile_expr($the_rest[1])); |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
} elsif ($op eq '++') { |
384
|
3
|
|
100
|
|
|
12
|
my $is_postfix = $the_rest[1] || 0; # set to 1 during postfix |
385
|
3
|
|
|
|
|
11
|
return "do { no warnings;\nmy \$val = 0 + ".$self->compile_expr($the_rest[0]).";\n" |
386
|
|
|
|
|
|
|
.$self->compile_expr($the_rest[0], "\$val + 1").";\n" |
387
|
|
|
|
|
|
|
."$is_postfix ? \$val : \$val + 1;\n}"; |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
} elsif ($op eq '--') { |
390
|
3
|
|
100
|
|
|
14
|
my $is_postfix = $the_rest[1] || 0; # set to 1 during postfix |
391
|
3
|
|
|
|
|
11
|
return "do { no warnings;\nmy \$val = 0 + ".$self->compile_expr($the_rest[0]).";\n" |
392
|
|
|
|
|
|
|
.$self->compile_expr($the_rest[0], "\$val - 1").";\n" |
393
|
|
|
|
|
|
|
."$is_postfix ? \$val : \$val - 1;\n}"; |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
} elsif ($op eq 'div' || $op eq 'DIV') { |
396
|
1
|
|
|
|
|
4
|
return "do { no warnings;\n int(".$self->compile_expr($the_rest[0])." / ".$self->compile_expr($the_rest[1]).")}"; |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
} elsif ($op eq '?') { |
399
|
23
|
|
|
|
|
60
|
return "do { no warnings;\n " .$self->compile_expr($the_rest[0]) |
400
|
|
|
|
|
|
|
." ? ".$self->compile_expr($the_rest[1]) |
401
|
|
|
|
|
|
|
." : ".$self->compile_expr($the_rest[2])." }"; |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
} elsif ($op eq '\\') { |
404
|
0
|
|
|
|
|
0
|
return do { local $self->{'_return_ref_ident'} = 1; $self->compile_expr($the_rest[0]) }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
} elsif ($op eq 'qr') { |
407
|
1
|
50
|
|
|
|
7
|
return $the_rest[1] ? "qr{(?$the_rest[1]:$the_rest[0])}" : "qr{$the_rest[0]}"; |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
} elsif (@the_rest == 1) { |
410
|
14
|
|
|
|
|
51
|
return $op.$self->compile_expr($the_rest[0]); |
411
|
|
|
|
|
|
|
} elsif ($op eq '//' || $op eq 'err') { |
412
|
65
|
|
|
|
|
161
|
return "do { my \$var = ".$self->compile_expr($the_rest[0])."; defined(\$var) ? \$var : ".$self->compile_expr($the_rest[1])."}"; |
413
|
|
|
|
|
|
|
} else { |
414
|
143
|
|
|
|
|
414
|
return "do { no warnings; ".$self->compile_expr($the_rest[0])." $op ".$self->compile_expr($the_rest[1])."}"; |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
### takes an already parsed identity |
419
|
|
|
|
|
|
|
### and strips it of args and outputs a string |
420
|
|
|
|
|
|
|
### so that the passing mechanism of Template::Directive |
421
|
|
|
|
|
|
|
### can hand off to set or get which will reparse again - wow and sigh |
422
|
|
|
|
|
|
|
sub compile_ident_str_from_cet { |
423
|
19
|
|
|
19
|
0
|
21
|
my ($self, $ident) = @_; |
424
|
19
|
50
|
|
|
|
35
|
return '' if ! defined $ident; |
425
|
19
|
50
|
|
|
|
37
|
return $ident if ! ref $ident; |
426
|
19
|
50
|
33
|
|
|
84
|
return '' if ref $ident->[0] || ! defined $ident->[0]; |
427
|
|
|
|
|
|
|
|
428
|
19
|
|
|
|
|
22
|
my $i = 0; |
429
|
19
|
|
|
|
|
25
|
my $str = $ident->[$i++]; |
430
|
19
|
|
|
|
|
18
|
$i++; # for args; |
431
|
|
|
|
|
|
|
|
432
|
19
|
|
|
|
|
43
|
while ($i < @$ident) { |
433
|
0
|
|
|
|
|
0
|
my $dot = $ident->[$i++]; |
434
|
0
|
0
|
|
|
|
0
|
return $str if $dot ne '.'; |
435
|
0
|
0
|
0
|
|
|
0
|
return $str if ref $ident->[$i] || ! defined $ident->[$i]; |
436
|
0
|
|
|
|
|
0
|
$str .= ".". $ident->[$i++]; |
437
|
0
|
|
|
|
|
0
|
$i++; # for args |
438
|
|
|
|
|
|
|
} |
439
|
19
|
|
|
|
|
82
|
return $str; |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
443
|
|
|
|
|
|
|
### everything in this section are the output of DIRECTIVES - as much as possible we |
444
|
|
|
|
|
|
|
### try to use the facilities provided by Template::Directive |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
sub compile_BLOCK { |
447
|
9
|
|
|
9
|
0
|
20
|
my ($self, $name, $node) = @_; |
448
|
9
|
|
|
|
|
40
|
$self->{'DEFBLOCK'}->{$name} = $self->{'FACTORY'}->template($self->compile_tree($node->[4])); |
449
|
9
|
|
|
|
|
176
|
return ''; |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
|
452
|
0
|
|
|
0
|
0
|
0
|
sub compile_BREAK { shift->{'FACTORY'}->break } |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
sub compile_CALL { |
455
|
1
|
|
|
1
|
0
|
1
|
my ($self, $ident) = @_; |
456
|
1
|
|
|
|
|
4
|
return $self->{'FACTORY'}->call($self->compile_expr($ident)); |
457
|
|
|
|
|
|
|
} |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
sub compile_CLEAR { |
460
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
461
|
0
|
|
|
|
|
0
|
return $self->{'FACTORY'}->clear; |
462
|
|
|
|
|
|
|
} |
463
|
|
|
|
|
|
|
|
464
|
2
|
|
|
2
|
0
|
4
|
sub compile_COMMENT {} |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
sub compile_CONFIG { |
467
|
0
|
|
|
0
|
0
|
0
|
my ($self, $config) = @_; |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
### prepare runtime config - not many options get these |
470
|
0
|
|
|
|
|
0
|
my ($named, @the_rest) = @$config; |
471
|
0
|
|
|
|
|
0
|
$named = $self->compile_named_args([$named])->[0]; |
472
|
0
|
|
|
|
|
0
|
$named = join ",", @$named; |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
### show what current values are |
475
|
0
|
|
|
|
|
0
|
my $items = join ",", map { s/\\([\'\$])/$1/g; "'$_'" } @the_rest; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
476
|
|
|
|
|
|
|
|
477
|
0
|
|
|
|
|
0
|
my $get = $self->{'FACTORY'}->get($self->{'FACTORY'}->ident(["'$TEMP_VARNAME'", 0])); |
478
|
0
|
|
|
|
|
0
|
return <
|
479
|
|
|
|
|
|
|
do { |
480
|
|
|
|
|
|
|
my \$conf = \$context->{'CONFIG'} ||= {}; |
481
|
|
|
|
|
|
|
my \$newconf = {$named}; |
482
|
|
|
|
|
|
|
\$conf->{\$_} = \$newconf->{\$_} foreach keys %\$newconf; |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
my \@items = ($items); |
485
|
|
|
|
|
|
|
if (\@items) { |
486
|
|
|
|
|
|
|
my \$str = join("\n", map { /(^[A-Z]+)\$/ ? ("CONFIG \$_ = ".(defined(\$conf->{\$_}) ? \$conf->{\$_} : 'undef')) : \$_ } \@items); |
487
|
|
|
|
|
|
|
\$stash->set(['$TEMP_VARNAME', 0], \$str); |
488
|
|
|
|
|
|
|
$get; |
489
|
|
|
|
|
|
|
\$stash->set(['$TEMP_VARNAME', 0], ''); |
490
|
|
|
|
|
|
|
} |
491
|
|
|
|
|
|
|
}; |
492
|
|
|
|
|
|
|
EOF |
493
|
|
|
|
|
|
|
} |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
sub compile_DEBUG { |
496
|
0
|
|
|
0
|
0
|
0
|
my ($self, $ref) = @_; |
497
|
0
|
|
|
|
|
0
|
my @options = "'$ref->[0]'"; |
498
|
0
|
0
|
|
|
|
0
|
if ($ref->[0] eq 'format') { |
|
|
0
|
|
|
|
|
|
499
|
0
|
|
|
|
|
0
|
my $format = $ref->[1]; |
500
|
0
|
|
|
|
|
0
|
$format =~ s/([\'\\])/\\$1/g; |
501
|
0
|
|
|
|
|
0
|
push @options, "'$format'"; |
502
|
|
|
|
|
|
|
} elsif (defined $self->{'_debug'}) { # defined if on at beginning |
503
|
0
|
0
|
|
|
|
0
|
if ($ref->[0] eq 'on') { |
|
|
0
|
|
|
|
|
|
504
|
0
|
|
|
|
|
0
|
$self->{'_debug'} = 1; |
505
|
|
|
|
|
|
|
} elsif ($ref->[0] eq 'off') { |
506
|
0
|
|
|
|
|
0
|
$self->{'_debug'} = 0; |
507
|
|
|
|
|
|
|
} |
508
|
|
|
|
|
|
|
} |
509
|
0
|
|
|
|
|
0
|
return $self->{'FACTORY'}->debug([\@options, [[]]]); |
510
|
|
|
|
|
|
|
} |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
sub compile_DEFAULT { |
513
|
3
|
|
|
3
|
0
|
4
|
my ($self, $set, $node) = @_; |
514
|
3
|
|
|
|
|
8
|
return $self->compile_SET($set, $node, 1); |
515
|
|
|
|
|
|
|
} |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
sub compile_DUMP { |
518
|
0
|
|
|
0
|
0
|
0
|
my ($self, $dump, $node) = @_; |
519
|
0
|
|
|
|
|
0
|
my $info = $self->node_info($node); |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
### This would work if the DUMP patch was accepted. It wasn't because of concerns about the size of the Grammar table |
522
|
|
|
|
|
|
|
# return $self->{'FACTORY'}->dump($self->compile_named_args($dump), $info->{'file'}, $info->{'line'}, \$info->{'text'}); |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
### so we'll inline the method here |
525
|
|
|
|
|
|
|
|
526
|
0
|
|
|
|
|
0
|
my $args = $self->compile_named_args($dump); |
527
|
0
|
|
|
|
|
0
|
my $_file = $info->{'file'}; |
528
|
0
|
|
|
|
|
0
|
my $_line = $info->{'line'}; |
529
|
0
|
|
|
|
|
0
|
my $_text = $info->{'text'}; |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
# add on named arguments as a final hashref |
532
|
0
|
|
|
|
|
0
|
my $named = shift @$args; |
533
|
0
|
0
|
|
|
|
0
|
push @$args, "{\n " . join(",\n ", @$named) . ",\n },\n" if @$named; |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
# prepare arguments to pass to Dumper |
536
|
0
|
0
|
|
|
|
0
|
my $_args = (@$args > 1) ? "[\n ". join(",\n ", @$args) .",\n ]" # treat multiple args as a single arrayref to help name align |
|
|
0
|
|
|
|
|
|
537
|
|
|
|
|
|
|
: (@$args > 0) ? $args->[0] # treat single item as a single item |
538
|
|
|
|
|
|
|
: '$stash'; # treat entire stash as one item |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
# find the name of the variables being dumped |
541
|
0
|
0
|
|
|
|
0
|
my $is_entire = ! @$args ? 1 : 0; |
542
|
0
|
0
|
|
|
|
0
|
my $_name = $is_entire ? 'EntireStash' : $_text; |
543
|
0
|
|
|
|
|
0
|
$_name =~ s/^.*?\bDUMP\s*//; |
544
|
0
|
|
|
|
|
0
|
s/\'/\\\'/g for $_name, $_file; |
545
|
|
|
|
|
|
|
|
546
|
0
|
|
|
|
|
0
|
my $get = $self->{'FACTORY'}->get($self->{'FACTORY'}->ident(["'$TEMP_VARNAME'", 0])); |
547
|
|
|
|
|
|
|
|
548
|
0
|
|
|
|
|
0
|
return <
|
549
|
|
|
|
|
|
|
do { |
550
|
|
|
|
|
|
|
# DUMP |
551
|
|
|
|
|
|
|
require Template::Parser::CET; |
552
|
|
|
|
|
|
|
\$stash->set(['$TEMP_VARNAME', 0], Template::Parser::CET->play_dump({ |
553
|
|
|
|
|
|
|
context => \$context, |
554
|
|
|
|
|
|
|
file => '$_file', |
555
|
|
|
|
|
|
|
line => $_line, |
556
|
|
|
|
|
|
|
name => '$_name', |
557
|
|
|
|
|
|
|
args => $_args, |
558
|
|
|
|
|
|
|
EntireStash => $is_entire, |
559
|
|
|
|
|
|
|
})); |
560
|
|
|
|
|
|
|
$get; |
561
|
|
|
|
|
|
|
\$stash->set(['$TEMP_VARNAME', 0], ''); |
562
|
|
|
|
|
|
|
}; |
563
|
|
|
|
|
|
|
EOF |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
} |
566
|
|
|
|
|
|
|
|
567
|
80
|
|
|
80
|
0
|
138
|
sub compile_END { '' } |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
sub compile_EVAL { |
570
|
0
|
|
|
0
|
0
|
0
|
my ($self, $ref, $node) = @_; |
571
|
0
|
|
|
|
|
0
|
my ($named, @strs) = @$ref; |
572
|
|
|
|
|
|
|
|
573
|
0
|
|
|
|
|
0
|
$named = [[]]; # TT doesn't allow args to eval ! $named ? [[]] : [[], map { $self->compile_expr($_) } @$named]; |
574
|
|
|
|
|
|
|
|
575
|
0
|
|
|
|
|
0
|
my $block = " |
576
|
0
|
|
|
|
|
0
|
foreach my \$str (".join(",\n", map {$self->compile_expr($_)} @strs).") { |
577
|
|
|
|
|
|
|
next if ! defined \$str; |
578
|
|
|
|
|
|
|
\$output .= \$str; # Alloy does them one at a time |
579
|
|
|
|
|
|
|
}"; |
580
|
|
|
|
|
|
|
|
581
|
0
|
|
|
|
|
0
|
$self->{'FACTORY'}->filter([["'eval'"], $named, ''], $block); |
582
|
|
|
|
|
|
|
} |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
sub compile_FILTER { |
585
|
17
|
|
|
17
|
0
|
30
|
my ($self, $ref, $node) = @_; |
586
|
17
|
|
|
|
|
24
|
my ($alias, $filter) = @$ref; |
587
|
|
|
|
|
|
|
|
588
|
17
|
|
|
|
|
34
|
my ($filt_name, $args) = @$filter; # doesn't support Template::Alloy chained filters |
589
|
|
|
|
|
|
|
|
590
|
17
|
100
|
|
|
|
49
|
$args = ! $args ? [[]] : [[], map { $self->compile_expr($_) } @$args]; |
|
10
|
|
|
|
|
23
|
|
591
|
|
|
|
|
|
|
|
592
|
17
|
|
|
|
|
58
|
$self->{'FACTORY'}->filter([[$self->compile_expr($filt_name)], |
593
|
|
|
|
|
|
|
$args, |
594
|
|
|
|
|
|
|
$self->compile_expr($alias) |
595
|
|
|
|
|
|
|
], |
596
|
|
|
|
|
|
|
$self->compile_tree($node->[4])); |
597
|
|
|
|
|
|
|
} |
598
|
|
|
|
|
|
|
|
599
|
4
|
|
|
4
|
0
|
20
|
sub compile_FOR { shift->compile_FOREACH(@_) } |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
sub compile_FOREACH { |
602
|
16
|
|
|
16
|
0
|
38
|
my ($self, $ref, $node) = @_; |
603
|
16
|
|
|
|
|
63
|
my ($var, $items) = @$ref; |
604
|
16
|
100
|
|
|
|
42
|
if ($var) { |
605
|
11
|
|
|
|
|
21
|
$var = $var->[0]; |
606
|
|
|
|
|
|
|
} |
607
|
|
|
|
|
|
|
|
608
|
16
|
|
|
|
|
52
|
$items = $self->compile_expr($items); |
609
|
|
|
|
|
|
|
|
610
|
16
|
|
|
|
|
79
|
local $self->{'loop_type'} = 'FOREACH'; |
611
|
16
|
|
|
|
|
70
|
return $self->{'FACTORY'}->foreach($var, $items, [[]], $self->compile_tree($node->[4])); |
612
|
|
|
|
|
|
|
} |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
sub compile_GET { |
615
|
707
|
|
|
707
|
0
|
1022
|
my ($self, $ident) = @_; |
616
|
707
|
|
|
|
|
1910
|
return $self->{'FACTORY'}->get($self->compile_expr($ident)); |
617
|
|
|
|
|
|
|
} |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
sub compile_IF { |
620
|
32
|
|
|
32
|
0
|
56
|
my ($self, $ref, $node, $unless) = @_; |
621
|
|
|
|
|
|
|
|
622
|
32
|
|
|
|
|
73
|
my $expr = $self->compile_expr($ref); |
623
|
32
|
50
|
|
|
|
429
|
$expr = "!$expr" if $unless; |
624
|
|
|
|
|
|
|
|
625
|
32
|
|
|
|
|
98
|
my $block = $self->compile_tree($node->[4]); |
626
|
|
|
|
|
|
|
|
627
|
32
|
|
|
|
|
229
|
my @elsif; |
628
|
|
|
|
|
|
|
my $had_else; |
629
|
32
|
|
|
|
|
90
|
while ($node = $node->[5]) { # ELSE, ELSIF's |
630
|
20
|
100
|
|
|
|
57
|
if ($node->[0] eq 'ELSE') { |
631
|
13
|
50
|
|
|
|
35
|
if ($node->[4]) { |
632
|
13
|
|
|
|
|
48
|
push @elsif, $self->compile_tree($node->[4]); |
633
|
13
|
|
|
|
|
96
|
$had_else = 1; |
634
|
|
|
|
|
|
|
} |
635
|
13
|
|
|
|
|
18
|
last; |
636
|
|
|
|
|
|
|
} |
637
|
7
|
|
|
|
|
54
|
my $_expr = $self->compile_expr($node->[3]); |
638
|
7
|
|
|
|
|
92
|
my $_block = $self->compile_tree($node->[4]); |
639
|
7
|
|
|
|
|
101
|
push @elsif, [$_expr, $_block]; |
640
|
|
|
|
|
|
|
} |
641
|
32
|
100
|
|
|
|
75
|
push @elsif, undef if ! $had_else; |
642
|
|
|
|
|
|
|
|
643
|
32
|
|
|
|
|
140
|
return $self->{'FACTORY'}->if($expr, $block, \@elsif); |
644
|
|
|
|
|
|
|
} |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
sub compile_INCLUDE { |
647
|
0
|
|
|
0
|
0
|
0
|
my ($self, $ref, $node) = @_; |
648
|
|
|
|
|
|
|
|
649
|
0
|
|
|
|
|
0
|
my ($named, @files) = @{ $self->compile_named_args($ref) }; |
|
0
|
|
|
|
|
0
|
|
650
|
|
|
|
|
|
|
|
651
|
0
|
|
|
|
|
0
|
return $self->{'FACTORY'}->include([\@files, [$named]]); |
652
|
|
|
|
|
|
|
} |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
sub compile_INSERT { |
655
|
3
|
|
|
3
|
0
|
7
|
my ($self, $ref, $node) = @_; |
656
|
|
|
|
|
|
|
|
657
|
3
|
|
|
|
|
5
|
my ($named, @files) = @{ $self->compile_named_args($ref) }; |
|
3
|
|
|
|
|
9
|
|
658
|
|
|
|
|
|
|
|
659
|
3
|
|
|
|
|
140
|
return $self->{'FACTORY'}->insert([\@files, [$named]]); |
660
|
|
|
|
|
|
|
} |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
sub compile_LAST { |
663
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
664
|
0
|
|
0
|
|
|
0
|
my $type = $self->{'loop_type'} || ''; |
665
|
0
|
0
|
0
|
|
|
0
|
return "last LOOP;\n" if $type eq 'WHILE' || $type eq 'FOREACH'; |
666
|
0
|
|
|
|
|
0
|
return "last;\n"; # the grammar nicely hard codes the choices |
667
|
0
|
|
|
|
|
0
|
return "last;\n"; |
668
|
|
|
|
|
|
|
} |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
sub compile_LOOP { |
671
|
15
|
|
|
15
|
0
|
29
|
my ($self, $ref, $node) = @_; |
672
|
15
|
100
|
|
|
|
38
|
$ref = [$ref, 0] if ! ref $ref; |
673
|
|
|
|
|
|
|
|
674
|
15
|
|
|
|
|
195
|
my $out = "do { |
675
|
|
|
|
|
|
|
my \$var = ".$self->compile_expr($ref)."; |
676
|
|
|
|
|
|
|
if (\$var) { |
677
|
|
|
|
|
|
|
my \$conf = \$context->{'CONFIG'} ||= {}; |
678
|
|
|
|
|
|
|
my \$global = ! \$conf->{'SYNTAX'} || \$conf->{'SYNTAX'} ne 'ht' || \$conf->{'GLOBAL_VARS'}; |
679
|
|
|
|
|
|
|
my \$items = ref(\$var) eq 'ARRAY' ? \$var : ref(\$var) eq 'HASH' ? [\$var] : []; |
680
|
|
|
|
|
|
|
my \$i = 0; |
681
|
|
|
|
|
|
|
for my \$ref (\@\$items) { |
682
|
|
|
|
|
|
|
\$context->throw('loop', 'Scalar value used in LOOP') if \$ref && ref(\$ref) ne 'HASH'; |
683
|
|
|
|
|
|
|
my \$stash = \$global ? \$stash : ref(\$stash)->new; |
684
|
|
|
|
|
|
|
\$stash = \$context->localise() if \$global; |
685
|
|
|
|
|
|
|
if (\$conf->{'LOOP_CONTEXT_VARS'} && ! \$Template::Stash::PRIVATE) { |
686
|
|
|
|
|
|
|
my \%set; |
687
|
|
|
|
|
|
|
\@set{qw(__counter__ __first__ __last__ __inner__ __odd__)} |
688
|
|
|
|
|
|
|
= (++\$i, (\$i == 1 ? 1 : 0), (\$i == \@\$items ? 1 : 0), (\$i == 1 || \$i == \@\$items ? 0 : 1), (\$i % 2) ? 1 : 0); |
689
|
|
|
|
|
|
|
\$stash->set(\$_, \$set{\$_}) foreach keys %set; |
690
|
|
|
|
|
|
|
} |
691
|
|
|
|
|
|
|
if (ref(\$ref) eq 'HASH') { |
692
|
|
|
|
|
|
|
\$stash->set(\$_, \$ref->{\$_}) foreach keys %\$ref; |
693
|
|
|
|
|
|
|
} |
694
|
|
|
|
|
|
|
".$self->compile_tree($node->[4])." |
695
|
|
|
|
|
|
|
\$stash = \$context->delocalise() if \$global; |
696
|
|
|
|
|
|
|
} |
697
|
|
|
|
|
|
|
} |
698
|
|
|
|
|
|
|
};"; |
699
|
15
|
|
|
|
|
247
|
return $out; |
700
|
|
|
|
|
|
|
} |
701
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
sub compile_MACRO { |
703
|
10
|
|
|
10
|
0
|
15
|
my ($self, $ref, $node) = @_; |
704
|
10
|
|
|
|
|
16
|
my ($name, $args) = @$ref; |
705
|
|
|
|
|
|
|
|
706
|
10
|
|
|
|
|
30
|
$name = $self->compile_ident_str_from_cet($name); |
707
|
10
|
100
|
|
|
|
27
|
$args = [map {$self->compile_ident_str_from_cet($_)} @$args] if $args; |
|
9
|
|
|
|
|
21
|
|
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
### get the sub tree |
710
|
10
|
|
|
|
|
15
|
my $sub_tree = $node->[4]; |
711
|
10
|
50
|
33
|
|
|
86
|
if (! $sub_tree || ! $sub_tree->[0]) { |
|
|
100
|
100
|
|
|
|
|
712
|
0
|
|
|
|
|
0
|
$self->set_variable($name, undef); |
713
|
0
|
|
|
|
|
0
|
return; |
714
|
|
|
|
|
|
|
} elsif (ref($sub_tree->[0]) && $sub_tree->[0]->[0] eq 'BLOCK') { |
715
|
3
|
|
|
|
|
7
|
$sub_tree = $sub_tree->[0]->[4]; |
716
|
|
|
|
|
|
|
} |
717
|
|
|
|
|
|
|
|
718
|
10
|
|
|
|
|
28
|
return $self->{'FACTORY'}->macro($name, $self->compile_tree($sub_tree), $args); |
719
|
|
|
|
|
|
|
} |
720
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
sub compile_META { |
722
|
2
|
|
|
2
|
0
|
5
|
my ($self, $hash, $node) = @_; |
723
|
2
|
50
|
|
|
|
10
|
push(@{ $self->{'METADATA'} }, %$hash) if $hash; |
|
2
|
|
|
|
|
46
|
|
724
|
0
|
|
|
|
|
0
|
return ''; |
725
|
|
|
|
|
|
|
} |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
sub compile_NEXT { |
728
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
729
|
0
|
|
0
|
|
|
0
|
my $type = $self->{'loop_type'} || ''; |
730
|
0
|
0
|
|
|
|
0
|
return $self->{'FACTORY'}->next if $type eq 'FOREACH'; |
731
|
0
|
0
|
|
|
|
0
|
return "next LOOP;\n" if $type eq 'WHILE'; |
732
|
0
|
|
|
|
|
0
|
return "next;\n"; |
733
|
|
|
|
|
|
|
} |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
sub compile_PERL { |
736
|
0
|
|
|
0
|
0
|
0
|
my ($self, $ref, $node) = @_; |
737
|
0
|
|
0
|
|
|
0
|
my $block = $node->[4] || return ''; |
738
|
0
|
0
|
|
|
|
0
|
return $self->{'FACTORY'}->no_perl if ! $self->{'EVAL_PERL'}; |
739
|
|
|
|
|
|
|
|
740
|
0
|
|
|
|
|
0
|
return $self->{'FACTORY'}->perl($self->compile_tree($block)); |
741
|
|
|
|
|
|
|
} |
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
sub compile_PROCESS { |
744
|
22
|
|
|
22
|
0
|
44
|
my ($self, $ref, $node) = @_; |
745
|
|
|
|
|
|
|
|
746
|
22
|
|
|
|
|
32
|
my ($named, @files) = @{ $self->compile_named_args($ref) }; |
|
22
|
|
|
|
|
59
|
|
747
|
|
|
|
|
|
|
|
748
|
22
|
|
|
|
|
270
|
return $self->{'FACTORY'}->process([\@files, [$named]]); |
749
|
|
|
|
|
|
|
} |
750
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
sub compile_RAWPERL { |
752
|
0
|
|
|
0
|
0
|
0
|
my ($self, $ref, $node) = @_; |
753
|
|
|
|
|
|
|
|
754
|
0
|
0
|
|
|
|
0
|
return $self->{'FACTORY'}->no_perl if ! $self->{'EVAL_PERL'}; |
755
|
|
|
|
|
|
|
|
756
|
0
|
|
0
|
|
|
0
|
my $block = $node->[4] || return ''; |
757
|
0
|
|
|
|
|
0
|
my $info = $self->node_info($node); |
758
|
0
|
|
|
|
|
0
|
my $txt = ''; |
759
|
0
|
|
|
|
|
0
|
foreach my $chunk (@$block) { |
760
|
0
|
0
|
|
|
|
0
|
next if ! defined $chunk; |
761
|
0
|
0
|
|
|
|
0
|
if (! ref $chunk) { |
762
|
0
|
|
|
|
|
0
|
$txt .= $chunk; |
763
|
0
|
|
|
|
|
0
|
next; |
764
|
|
|
|
|
|
|
} |
765
|
0
|
0
|
|
|
|
0
|
next if $chunk->[0] eq 'END'; |
766
|
0
|
|
|
|
|
0
|
die "Handling of $chunk->[0] not yet implemented in RAWPERL"; |
767
|
|
|
|
|
|
|
} |
768
|
|
|
|
|
|
|
|
769
|
0
|
|
|
|
|
0
|
return $self->{'FACTORY'}->rawperl($txt, $info->{'line'}); |
770
|
|
|
|
|
|
|
} |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
sub compile_RETURN { |
773
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
774
|
0
|
|
|
|
|
0
|
return $self->{'FACTORY'}->return; |
775
|
|
|
|
|
|
|
} |
776
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
sub compile_SET { |
778
|
173
|
|
|
173
|
0
|
273
|
my ($self, $set, $node, $default) = @_; |
779
|
|
|
|
|
|
|
|
780
|
173
|
|
|
|
|
236
|
my $out = ''; |
781
|
173
|
|
|
|
|
357
|
foreach (@$set) { |
782
|
177
|
|
|
|
|
386
|
my ($op, $set, $val) = @$_; |
783
|
|
|
|
|
|
|
|
784
|
177
|
100
|
66
|
|
|
732
|
if (! defined $val) { # not defined |
|
|
100
|
|
|
|
|
|
785
|
4
|
|
|
|
|
8
|
$val = "''"; |
786
|
|
|
|
|
|
|
} elsif ($node->[4] && $val == $node->[4]) { # a captured directive |
787
|
2
|
|
|
|
|
5
|
my $sub_tree = $node->[4]; |
788
|
2
|
50
|
33
|
|
|
50
|
$sub_tree = $sub_tree->[0]->[4] if $sub_tree->[0] && $sub_tree->[0]->[0] eq 'BLOCK'; |
789
|
2
|
|
|
|
|
5
|
$set = do { local $self->{'_return_capture_ident'} = 1; $self->compile_expr($set) }; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
7
|
|
790
|
2
|
|
|
|
|
10
|
$out .= $self->{'FACTORY'}->capture($set, $self->compile_tree($sub_tree)); |
791
|
2
|
|
|
|
|
48
|
next; |
792
|
|
|
|
|
|
|
} else { # normal var |
793
|
171
|
|
|
|
|
409
|
$val = $self->compile_expr($val); |
794
|
|
|
|
|
|
|
} |
795
|
|
|
|
|
|
|
|
796
|
175
|
50
|
|
|
|
2941
|
if ($OP_DISPATCH->{$op}) { |
797
|
0
|
0
|
|
|
|
0
|
$op =~ /^([^\w\s\$]+)=$/ || die "Not sure how to handle that op $op during SET"; |
798
|
0
|
0
|
0
|
|
|
0
|
my $short = ($1 eq '_' || $1 eq '~') ? '.' : $1; |
799
|
0
|
|
|
|
|
0
|
$val = "do { no warnings;\n". $self->compile_expr($set) ." $short $val}"; |
800
|
|
|
|
|
|
|
} |
801
|
|
|
|
|
|
|
|
802
|
175
|
|
|
|
|
370
|
$out .= $self->compile_expr($set, $val, $default).";\n"; |
803
|
|
|
|
|
|
|
} |
804
|
|
|
|
|
|
|
|
805
|
173
|
|
|
|
|
3013
|
return $out; |
806
|
|
|
|
|
|
|
} |
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
sub compile_STOP { |
809
|
5
|
|
|
5
|
0
|
6
|
my $self = shift; |
810
|
5
|
|
|
|
|
23
|
return $self->{'FACTORY'}->stop; |
811
|
|
|
|
|
|
|
} |
812
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
sub compile_SWITCH { |
814
|
0
|
|
|
0
|
0
|
0
|
my ($self, $var, $node) = @_; |
815
|
|
|
|
|
|
|
|
816
|
0
|
|
|
|
|
0
|
my $expr = $self->compile_expr($var); |
817
|
|
|
|
|
|
|
### $node->[4] is thrown away |
818
|
|
|
|
|
|
|
|
819
|
0
|
|
|
|
|
0
|
my @cases; |
820
|
|
|
|
|
|
|
my $default; |
821
|
0
|
|
|
|
|
0
|
while ($node = $node->[5]) { # CASES |
822
|
0
|
|
|
|
|
0
|
my $var = $node->[3]; |
823
|
0
|
|
|
|
|
0
|
my $block = $self->compile_tree($node->[4]); |
824
|
0
|
0
|
|
|
|
0
|
if (! defined $var) { |
825
|
0
|
|
|
|
|
0
|
$default = $block; |
826
|
0
|
|
|
|
|
0
|
next; |
827
|
|
|
|
|
|
|
} |
828
|
|
|
|
|
|
|
|
829
|
0
|
|
|
|
|
0
|
$var = $self->compile_expr($var); |
830
|
0
|
|
|
|
|
0
|
push @cases, [$var, $block]; |
831
|
|
|
|
|
|
|
} |
832
|
0
|
|
|
|
|
0
|
push @cases, $default; |
833
|
|
|
|
|
|
|
|
834
|
0
|
|
|
|
|
0
|
return $self->{'FACTORY'}->switch($expr, \@cases); |
835
|
|
|
|
|
|
|
} |
836
|
|
|
|
|
|
|
|
837
|
0
|
|
|
0
|
0
|
0
|
sub compile_TAGS { '' } # doesn't really do anything - but needs to be in the parse tree |
838
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
sub compile_THROW { |
840
|
0
|
|
|
0
|
0
|
0
|
my ($self, $ref) = @_; |
841
|
0
|
|
|
|
|
0
|
my ($name, $args) = @$ref; |
842
|
|
|
|
|
|
|
|
843
|
0
|
|
|
|
|
0
|
$name = $self->compile_expr($name); |
844
|
|
|
|
|
|
|
|
845
|
0
|
|
|
|
|
0
|
$self->{'FACTORY'}->throw([[$name], $self->compile_named_args($args)]); |
846
|
|
|
|
|
|
|
} |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
sub compile_TRY { |
849
|
0
|
|
|
0
|
0
|
0
|
my ($self, $foo, $node, $out_ref) = @_; |
850
|
0
|
|
|
|
|
0
|
my $out = ''; |
851
|
|
|
|
|
|
|
|
852
|
0
|
|
|
|
|
0
|
my $block = $self->compile_tree($node->[4]); |
853
|
|
|
|
|
|
|
|
854
|
0
|
|
|
|
|
0
|
my @catches; |
855
|
|
|
|
|
|
|
my $had_final; |
856
|
0
|
|
|
|
|
0
|
while ($node = $node->[5]) { # FINAL, CATCHES |
857
|
0
|
0
|
|
|
|
0
|
if ($node->[0] eq 'FINAL') { |
858
|
0
|
0
|
|
|
|
0
|
if ($node->[4]) { |
859
|
0
|
|
|
|
|
0
|
$had_final = $self->compile_tree($node->[4]); |
860
|
|
|
|
|
|
|
} |
861
|
0
|
|
|
|
|
0
|
next; |
862
|
|
|
|
|
|
|
} |
863
|
0
|
0
|
0
|
|
|
0
|
my $_expr = defined($node->[3]) && uc($node->[3]) ne 'DEFAULT' ? $node->[3] : ''; #$self->compile_expr($node->[3]); |
864
|
0
|
|
|
|
|
0
|
my $_block = $self->compile_tree($node->[4]); |
865
|
0
|
|
|
|
|
0
|
push @catches, [$_expr, $_block]; |
866
|
|
|
|
|
|
|
} |
867
|
0
|
|
|
|
|
0
|
push @catches, $had_final; |
868
|
|
|
|
|
|
|
|
869
|
0
|
|
|
|
|
0
|
return $self->{'FACTORY'}->try($block, \@catches); |
870
|
|
|
|
|
|
|
} |
871
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
sub compile_UNLESS { |
873
|
2
|
|
|
2
|
0
|
6
|
return shift->compile_IF(@_); |
874
|
|
|
|
|
|
|
} |
875
|
|
|
|
|
|
|
|
876
|
|
|
|
|
|
|
sub compile_USE { |
877
|
0
|
|
|
0
|
0
|
0
|
my ($self, $ref) = @_; |
878
|
0
|
|
|
|
|
0
|
my ($var, $module, $args) = @$ref; |
879
|
|
|
|
|
|
|
|
880
|
0
|
0
|
|
|
|
0
|
$var = $self->compile_expr($var) if defined $var; |
881
|
|
|
|
|
|
|
|
882
|
0
|
|
|
|
|
0
|
return $self->{'FACTORY'}->use([[$self->compile_expr($module)], $self->compile_named_args($args), $var]); |
883
|
|
|
|
|
|
|
} |
884
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
sub compile_VIEW { |
886
|
0
|
|
|
0
|
0
|
0
|
my ($self, $ref, $node) = @_; |
887
|
|
|
|
|
|
|
|
888
|
0
|
|
|
|
|
0
|
my ($blocks, $args, $viewname) = @$ref; |
889
|
|
|
|
|
|
|
|
890
|
0
|
|
|
|
|
0
|
$viewname = $self->compile_ident_str_from_cet($viewname); |
891
|
0
|
|
|
|
|
0
|
$viewname =~ s/\\\'/\'/g; |
892
|
0
|
|
|
|
|
0
|
$viewname = "'$viewname'"; |
893
|
|
|
|
|
|
|
|
894
|
0
|
|
|
|
|
0
|
my $named = $self->compile_named_args([$args])->[0]; |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
### prepare the blocks |
897
|
|
|
|
|
|
|
#my $prefix = $hash->{'prefix'} || (ref($name) && @$name == 2 && ! $name->[1] && ! ref($name->[0])) ? "$name->[0]/" : ''; |
898
|
0
|
|
|
|
|
0
|
foreach my $key (keys %$blocks) { |
899
|
0
|
|
|
|
|
0
|
$blocks->{$key} = $self->{'FACTORY'}->template($self->compile_tree($blocks->{$key})); #{name => "${prefix}${key}", _tree => $blocks->{$key}}; |
900
|
|
|
|
|
|
|
} |
901
|
|
|
|
|
|
|
|
902
|
0
|
|
|
|
|
0
|
my $block = $self->compile_tree($node->[4]); |
903
|
0
|
|
|
|
|
0
|
my $stuff= $self->{'FACTORY'}->view([[$viewname], [$named]], $block, $blocks); |
904
|
|
|
|
|
|
|
# print "---------------------\n". $stuff ."------------------------------\n"; |
905
|
0
|
|
|
|
|
0
|
return $stuff; |
906
|
|
|
|
|
|
|
} |
907
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
sub compile_WHILE { |
909
|
0
|
|
|
0
|
0
|
0
|
my ($self, $ref, $node) = @_; |
910
|
|
|
|
|
|
|
|
911
|
0
|
|
|
|
|
0
|
my $expr = $self->compile_expr($ref); |
912
|
|
|
|
|
|
|
|
913
|
0
|
|
|
|
|
0
|
local $self->{'loop_type'} = 'WHILE'; |
914
|
0
|
|
|
|
|
0
|
my $block = $self->compile_tree($node->[4]); |
915
|
|
|
|
|
|
|
|
916
|
0
|
|
|
|
|
0
|
return $self->{'FACTORY'}->while($expr, $block); |
917
|
|
|
|
|
|
|
} |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
sub compile_WRAPPER { |
920
|
0
|
|
|
0
|
0
|
0
|
my ($self, $ref, $node) = @_; |
921
|
|
|
|
|
|
|
|
922
|
0
|
|
|
|
|
0
|
my ($named, @files) = @{ $self->compile_named_args($ref) }; |
|
0
|
|
|
|
|
0
|
|
923
|
|
|
|
|
|
|
|
924
|
0
|
|
|
|
|
0
|
return $self->{'FACTORY'}->wrapper([\@files, [$named]], $self->compile_tree($node->[4])); |
925
|
|
|
|
|
|
|
} |
926
|
|
|
|
|
|
|
|
927
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
928
|
|
|
|
|
|
|
### Install some CET vmethods that dont' exist in TT2 as of 2.19 |
929
|
|
|
|
|
|
|
|
930
|
|
|
|
|
|
|
if (! $NO_LOAD_EXTRA_VMETHODS |
931
|
|
|
|
|
|
|
&& eval {require Template::Stash}) { |
932
|
|
|
|
|
|
|
|
933
|
|
|
|
|
|
|
for my $meth (qw(0 abs atan2 cos exp fmt hex int js lc log oct rand sin sprintf sqrt uc)) { |
934
|
|
|
|
|
|
|
next if defined $Template::Stash::SCALAR_OPS{$meth}; |
935
|
|
|
|
|
|
|
Template::Stash->define_vmethod('scalar', $meth => $Template::Alloy::SCALAR_OPS->{$meth}); |
936
|
|
|
|
|
|
|
} |
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
for my $meth (qw(fmt pick)) { |
939
|
|
|
|
|
|
|
next if defined $Template::Stash::LIST_OPS{$meth}; |
940
|
|
|
|
|
|
|
Template::Stash->define_vmethod('list', $meth => $Template::Alloy::LIST_OPS->{$meth}); |
941
|
|
|
|
|
|
|
} |
942
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
for my $meth (qw(fmt)) { |
944
|
|
|
|
|
|
|
next if defined $Template::Stash::HASH_OPS{$meth}; |
945
|
|
|
|
|
|
|
Template::Stash->define_vmethod('hash', $meth => $Template::Alloy::HASH_OPS->{$meth}); |
946
|
|
|
|
|
|
|
} |
947
|
|
|
|
|
|
|
} |
948
|
|
|
|
|
|
|
|
949
|
|
|
|
|
|
|
sub add_top_level_functions { |
950
|
571
|
|
|
571
|
0
|
852434
|
my ($class, $hash) = @_; |
951
|
571
|
|
|
|
|
784
|
eval {require Template::Stash}; |
|
571
|
|
|
|
|
3249
|
|
952
|
571
|
|
|
|
|
702
|
foreach (keys %{ $Template::Stash::SCALAR_OPS }) { |
|
571
|
|
|
|
|
4232
|
|
953
|
23411
|
50
|
|
|
|
44826
|
next if defined $hash->{$_}; |
954
|
23411
|
|
|
|
|
41143
|
$hash->{$_} = $Template::Stash::SCALAR_OPS->{$_}; |
955
|
|
|
|
|
|
|
} |
956
|
571
|
|
|
|
|
2357
|
foreach (keys %{ $Template::Alloy::VOBJS }) { |
|
571
|
|
|
|
|
1643
|
|
957
|
1713
|
50
|
|
|
|
3674
|
next if defined $hash->{$_}; |
958
|
1713
|
|
|
|
|
4204
|
$hash->{$_} = $Template::Alloy::VOBJS->{$_}; |
959
|
|
|
|
|
|
|
} |
960
|
|
|
|
|
|
|
} |
961
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
963
|
|
|
|
|
|
|
### handle the playing of the DUMP directive since it the patch wasn't accepted |
964
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
sub play_dump { |
966
|
0
|
|
|
0
|
0
|
|
my ($class, $info) = @_; |
967
|
0
|
|
0
|
|
|
|
my $context = $info->{'context'} || die "Missing context"; |
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
# find configuration overrides |
970
|
0
|
|
|
|
|
|
my $conf = $context->{'CONFIG'}->{'DUMP'}; |
971
|
0
|
0
|
0
|
|
|
|
return '' if ! $conf && defined $conf; # DUMP => 0 |
972
|
0
|
0
|
|
|
|
|
$conf = {} if ref $conf ne 'HASH'; |
973
|
|
|
|
|
|
|
|
974
|
0
|
|
|
|
|
|
my ($file, $line, $name, $args, $EntireStash) = @{ $info }{qw(file line name args EntireStash)}; |
|
0
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
# allow for handler override |
977
|
0
|
|
|
|
|
|
my $handler = $conf->{'handler'}; |
978
|
0
|
0
|
|
|
|
|
if (! $handler) { |
979
|
0
|
|
|
|
|
|
require Data::Dumper; |
980
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
# new object and configure it with keys that it understands |
982
|
0
|
|
|
|
|
|
my $obj = Data::Dumper->new([]); |
983
|
0
|
|
|
|
|
|
my $meth; |
984
|
0
|
|
|
|
|
|
foreach my $prop (keys %$conf) { |
985
|
0
|
0
|
0
|
|
|
|
$obj->$prop($conf->{$prop}) if $prop =~ /^\w+$/ && ($meth = $obj->can($prop)); |
986
|
|
|
|
|
|
|
} |
987
|
|
|
|
|
|
|
|
988
|
|
|
|
|
|
|
# add in custom Sortkeys handler that can trim out private variables |
989
|
0
|
0
|
|
|
|
|
my $sort = defined($conf->{'Sortkeys'}) ? $obj->Sortkeys : 1; |
990
|
0
|
0
|
|
0
|
|
|
$obj->Sortkeys(sub { my $h = shift; [grep {$_ !~ $Template::Stash::PRIVATE} ($sort ? sort keys %$h : keys %$h)] }); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
991
|
|
|
|
|
|
|
|
992
|
0
|
|
|
0
|
|
|
$handler = sub { $obj->Values([@_]); $obj->Dump } |
|
0
|
|
|
|
|
|
|
993
|
0
|
|
|
|
|
|
} |
994
|
|
|
|
|
|
|
|
995
|
|
|
|
|
|
|
# play the handler |
996
|
0
|
|
|
|
|
|
my $out; |
997
|
0
|
0
|
0
|
|
|
|
if (! $EntireStash # always play if not EntireStash |
|
|
|
0
|
|
|
|
|
998
|
|
|
|
|
|
|
|| $conf->{'EntireStash'} # explicitly set |
999
|
|
|
|
|
|
|
|| ! defined $conf->{'EntireStash'} # default to on |
1000
|
|
|
|
|
|
|
) { |
1001
|
0
|
0
|
|
|
|
|
delete $args->{$TEMP_VARNAME} if $EntireStash; |
1002
|
0
|
|
|
|
|
|
$out = $handler->($args); |
1003
|
|
|
|
|
|
|
} |
1004
|
0
|
0
|
|
|
|
|
$out = '' if ! defined $out; |
1005
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
# show our variable names |
1007
|
0
|
0
|
|
|
|
|
$EntireStash ? $out =~ s/\$VAR1/$name/g : $out =~ s/\$VAR1/$name/; |
1008
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
# add headers and formatting |
1010
|
0
|
0
|
0
|
|
|
|
if ($conf->{'html'} # explicitly html |
|
|
|
0
|
|
|
|
|
1011
|
|
|
|
|
|
|
|| (! defined($conf->{'html'}) # or not explicitly no html |
1012
|
|
|
|
|
|
|
&& $ENV{'REQUEST_METHOD'} # and looks like a web request |
1013
|
|
|
|
|
|
|
)) { |
1014
|
0
|
0
|
|
|
|
|
if (defined $out) { |
1015
|
0
|
|
|
|
|
|
$out = $context->filter('html')->($out); |
1016
|
0
|
|
|
|
|
|
$out = "$out "; |
1017
|
|
|
|
|
|
|
} |
1018
|
0
|
0
|
0
|
|
|
|
$out = "DUMP: File \"$info->{file}\" line $info->{line}$out" if $conf->{'header'} || ! defined $conf->{'header'}; |
1019
|
|
|
|
|
|
|
} else { |
1020
|
0
|
0
|
0
|
|
|
|
$out = "DUMP: File \"$info->{file}\" line $info->{line}\n $out" if $conf->{'header'} || ! defined $conf->{'header'}; |
1021
|
|
|
|
|
|
|
} |
1022
|
|
|
|
|
|
|
|
1023
|
0
|
|
|
|
|
|
return $out; |
1024
|
|
|
|
|
|
|
} |
1025
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
1027
|
|
|
|
|
|
|
|
1028
|
|
|
|
|
|
|
1; |
1029
|
|
|
|
|
|
|
|
1030
|
|
|
|
|
|
|
__END__ |