| 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__ |