line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Text::Handlebars::Compiler; |
2
|
|
|
|
|
|
|
BEGIN { |
3
|
12
|
|
|
12
|
|
689693
|
$Text::Handlebars::Compiler::AUTHORITY = 'cpan:DOY'; |
4
|
|
|
|
|
|
|
} |
5
|
|
|
|
|
|
|
$Text::Handlebars::Compiler::VERSION = '0.04'; |
6
|
12
|
|
|
12
|
|
123
|
use Mouse; |
|
12
|
|
|
|
|
27
|
|
|
12
|
|
|
|
|
121
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
extends 'Text::Xslate::Compiler'; |
9
|
|
|
|
|
|
|
|
10
|
12
|
|
|
12
|
|
6573
|
use Try::Tiny; |
|
12
|
|
|
|
|
27
|
|
|
12
|
|
|
|
|
57537
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
has '+syntax' => ( |
13
|
|
|
|
|
|
|
default => 'Handlebars', |
14
|
|
|
|
|
|
|
); |
15
|
|
|
|
|
|
|
|
16
|
160
|
|
|
160
|
0
|
901
|
sub define_helper { shift->parser->define_helper(@_) } |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
sub _generate_block_body { |
19
|
70
|
|
|
70
|
|
23484
|
my $self = shift; |
20
|
70
|
|
|
|
|
119
|
my ($node) = @_; |
21
|
|
|
|
|
|
|
|
22
|
70
|
|
|
|
|
112
|
my @compiled = map { $self->compile_ast($_) } @{ $node->second }; |
|
70
|
|
|
|
|
215
|
|
|
70
|
|
|
|
|
240
|
|
23
|
|
|
|
|
|
|
|
24
|
70
|
100
|
|
|
|
18058
|
unshift @compiled, $self->_localize_vars($node->first) |
25
|
|
|
|
|
|
|
if $node->first; |
26
|
|
|
|
|
|
|
|
27
|
70
|
|
|
|
|
4496
|
return @compiled; |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub _generate_key { |
31
|
681
|
|
|
681
|
|
191219
|
my $self = shift; |
32
|
681
|
|
|
|
|
1124
|
my ($node) = @_; |
33
|
|
|
|
|
|
|
|
34
|
681
|
|
|
|
|
2617
|
my $var = $node->clone(arity => 'variable'); |
35
|
|
|
|
|
|
|
|
36
|
681
|
|
|
|
|
26049
|
return $self->compile_ast($self->check_lambda($var)); |
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
sub _generate_key_field { |
40
|
66
|
|
|
66
|
|
27216
|
my $self = shift; |
41
|
66
|
|
|
|
|
123
|
my ($node) = @_; |
42
|
|
|
|
|
|
|
|
43
|
66
|
|
|
|
|
217
|
my $field = $node->clone(arity => 'field'); |
44
|
|
|
|
|
|
|
|
45
|
66
|
|
|
|
|
1902
|
return $self->compile_ast($self->check_lambda($field)); |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub _generate_call { |
49
|
1673
|
|
|
1673
|
|
84129
|
my $self = shift; |
50
|
1673
|
|
|
|
|
2795
|
my ($node) = @_; |
51
|
|
|
|
|
|
|
|
52
|
1673
|
100
|
|
|
|
6445
|
if ($node->is_helper) { |
53
|
41
|
|
|
|
|
62
|
my @args; |
54
|
|
|
|
|
|
|
my @hash; |
55
|
41
|
|
|
|
|
142
|
for my $arg (@{ $node->second }) { |
|
41
|
|
|
|
|
2134
|
|
56
|
42
|
100
|
|
|
|
178
|
if ($arg->arity eq 'pair') { |
57
|
4
|
|
|
|
|
22
|
push @hash, $arg->first, $arg->second; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
else { |
60
|
38
|
|
|
|
|
124
|
push @args, $arg; |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
41
|
|
|
|
|
198
|
my $hash = $self->make_hash(@hash); |
65
|
|
|
|
|
|
|
|
66
|
41
|
|
|
|
|
1697
|
unshift @args, $self->vars; |
67
|
|
|
|
|
|
|
|
68
|
41
|
100
|
|
|
|
1324
|
if ($node->is_block_helper) { |
69
|
33
|
|
|
|
|
55
|
push @{ $node->first->second }, $hash; |
|
33
|
|
|
|
|
148
|
|
70
|
33
|
|
|
|
|
130
|
$node->second(\@args); |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
else { |
73
|
8
|
|
|
|
|
38
|
$node->second([ @args, $hash ]); |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
1673
|
|
|
|
|
6212
|
return $self->SUPER::_generate_call($node); |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
sub _generate_partial { |
81
|
3
|
|
|
3
|
|
233
|
my $self = shift; |
82
|
3
|
|
|
|
|
7
|
my ($node) = @_; |
83
|
|
|
|
|
|
|
|
84
|
3
|
|
|
|
|
11
|
my $file = $node->first; |
85
|
3
|
50
|
|
|
|
12
|
if (ref($file) eq 'ARRAY') { |
86
|
3
|
|
|
|
|
30
|
$file = $node->clone( |
87
|
|
|
|
|
|
|
arity => 'binary', |
88
|
|
|
|
|
|
|
id => '~', |
89
|
|
|
|
|
|
|
first => $file->[0], |
90
|
|
|
|
|
|
|
second => $node->clone(arity => 'suffix'), |
91
|
|
|
|
|
|
|
); |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
3
|
|
|
|
|
157
|
my $args = $node->second; |
95
|
3
|
100
|
|
|
|
104
|
if ($args) { |
96
|
1
|
|
|
|
|
4
|
$args = [ $self->new_vars($args) ]; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
return ( |
100
|
3
|
|
|
|
|
78
|
$self->compile_ast( |
101
|
|
|
|
|
|
|
$self->make_ternary( |
102
|
|
|
|
|
|
|
$self->find_file($file->clone), |
103
|
|
|
|
|
|
|
$node->clone( |
104
|
|
|
|
|
|
|
arity => 'include', |
105
|
|
|
|
|
|
|
id => 'include', |
106
|
|
|
|
|
|
|
first => $file->clone, |
107
|
|
|
|
|
|
|
second => $args, |
108
|
|
|
|
|
|
|
), |
109
|
|
|
|
|
|
|
$self->literal(''), |
110
|
|
|
|
|
|
|
), |
111
|
|
|
|
|
|
|
), |
112
|
|
|
|
|
|
|
); |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
sub _generate_suffix { |
116
|
6
|
|
|
6
|
|
520
|
my $self = shift; |
117
|
6
|
|
|
|
|
9
|
my ($node) = @_; |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
return ( |
120
|
6
|
|
|
|
|
18
|
$self->opcode('suffix'), |
121
|
|
|
|
|
|
|
); |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub find_file { |
125
|
3
|
|
|
3
|
0
|
59
|
my $self = shift; |
126
|
3
|
|
|
|
|
8
|
my ($filename) = @_; |
127
|
|
|
|
|
|
|
|
128
|
3
|
|
|
|
|
13
|
return $filename->clone( |
129
|
|
|
|
|
|
|
arity => 'unary', |
130
|
|
|
|
|
|
|
id => 'find_file', |
131
|
|
|
|
|
|
|
first => $filename, |
132
|
|
|
|
|
|
|
); |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub _generate_for { |
136
|
35
|
|
|
35
|
|
17634
|
my $self = shift; |
137
|
35
|
|
|
|
|
65
|
my ($node) = @_; |
138
|
|
|
|
|
|
|
|
139
|
35
|
|
|
|
|
406
|
my @opcodes = $self->SUPER::_generate_for(@_); |
140
|
|
|
|
|
|
|
return ( |
141
|
35
|
|
|
|
|
43027
|
@opcodes, |
142
|
|
|
|
|
|
|
$self->opcode('nil'), |
143
|
|
|
|
|
|
|
); |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub _generate_block { |
147
|
68
|
|
|
68
|
|
13652
|
my $self = shift; |
148
|
68
|
|
|
|
|
144
|
my ($node) = @_; |
149
|
|
|
|
|
|
|
|
150
|
68
|
|
|
|
|
593
|
my $name = $node->first; |
151
|
68
|
|
|
|
|
121
|
my %block = %{ $node->second }; |
|
68
|
|
|
|
|
479
|
|
152
|
|
|
|
|
|
|
|
153
|
68
|
100
|
|
|
|
453
|
if ($name->arity eq 'call') { |
154
|
33
|
100
|
|
|
|
154
|
return $self->compile_ast( |
155
|
|
|
|
|
|
|
$name->clone( |
156
|
|
|
|
|
|
|
first => $self->call( |
157
|
|
|
|
|
|
|
$node, |
158
|
|
|
|
|
|
|
'(make_block_helper)', |
159
|
|
|
|
|
|
|
$self->vars, |
160
|
|
|
|
|
|
|
$name->first, |
161
|
|
|
|
|
|
|
$block{if}{raw_text}->clone, |
162
|
|
|
|
|
|
|
($block{else} |
163
|
|
|
|
|
|
|
? $block{else}{raw_text}->clone |
164
|
|
|
|
|
|
|
: $self->literal('')), |
165
|
|
|
|
|
|
|
), |
166
|
|
|
|
|
|
|
is_block_helper => 1, |
167
|
|
|
|
|
|
|
), |
168
|
|
|
|
|
|
|
); |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
35
|
|
|
|
|
147
|
my $iterations = $self->make_ternary( |
172
|
|
|
|
|
|
|
$self->is_falsy($name->clone), |
173
|
|
|
|
|
|
|
$self->make_array($self->literal(1)), |
174
|
|
|
|
|
|
|
$self->make_ternary( |
175
|
|
|
|
|
|
|
$self->is_array_ref($name->clone), |
176
|
|
|
|
|
|
|
$name->clone, |
177
|
|
|
|
|
|
|
$self->make_array($self->literal(1)), |
178
|
|
|
|
|
|
|
), |
179
|
|
|
|
|
|
|
); |
180
|
|
|
|
|
|
|
|
181
|
35
|
|
|
|
|
13973
|
my $loop_var = $self->parser->symbol('(loop_var)')->clone(arity => 'variable'); |
182
|
|
|
|
|
|
|
|
183
|
35
|
|
|
|
|
2864
|
my $body_block = [ |
184
|
|
|
|
|
|
|
$self->make_ternary( |
185
|
|
|
|
|
|
|
$self->is_falsy($name->clone), |
186
|
|
|
|
|
|
|
$name->clone( |
187
|
|
|
|
|
|
|
arity => 'block_body', |
188
|
|
|
|
|
|
|
first => undef, |
189
|
|
|
|
|
|
|
second => [ $block{else}{body} ], |
190
|
|
|
|
|
|
|
), |
191
|
|
|
|
|
|
|
$name->clone( |
192
|
|
|
|
|
|
|
arity => 'block_body', |
193
|
|
|
|
|
|
|
first => [ |
194
|
|
|
|
|
|
|
$self->new_vars($name->clone, $self->iterator_index), |
195
|
|
|
|
|
|
|
], |
196
|
|
|
|
|
|
|
second => [ $block{if}{body} ], |
197
|
|
|
|
|
|
|
), |
198
|
|
|
|
|
|
|
), |
199
|
|
|
|
|
|
|
]; |
200
|
|
|
|
|
|
|
|
201
|
35
|
|
|
|
|
1501
|
my $var = $name->clone(arity => 'variable'); |
202
|
35
|
|
|
|
|
996
|
return $self->compile_ast( |
203
|
|
|
|
|
|
|
$self->make_ternary( |
204
|
|
|
|
|
|
|
$self->is_code_ref($var->clone), |
205
|
|
|
|
|
|
|
$self->run_code( |
206
|
|
|
|
|
|
|
$var->clone, |
207
|
|
|
|
|
|
|
$block{if}{raw_text}->clone, |
208
|
|
|
|
|
|
|
$block{if}{open_tag}->clone, |
209
|
|
|
|
|
|
|
$block{if}{close_tag}->clone, |
210
|
|
|
|
|
|
|
), |
211
|
|
|
|
|
|
|
$self->parser->symbol('(for)')->clone( |
212
|
|
|
|
|
|
|
arity => 'for', |
213
|
|
|
|
|
|
|
first => $iterations, |
214
|
|
|
|
|
|
|
second => [$loop_var], |
215
|
|
|
|
|
|
|
third => $body_block, |
216
|
|
|
|
|
|
|
), |
217
|
|
|
|
|
|
|
), |
218
|
|
|
|
|
|
|
); |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub _generate_unary { |
222
|
1067
|
|
|
1067
|
|
140769
|
my $self = shift; |
223
|
1067
|
|
|
|
|
1504
|
my ($node) = @_; |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
# XXX copied from Text::Xslate::Compiler because it uses a hardcoded list |
226
|
|
|
|
|
|
|
# of unary ops |
227
|
1067
|
100
|
|
|
|
3578
|
if ($self->is_unary($node->id)) { |
228
|
997
|
|
|
|
|
6276
|
my @code = ( |
229
|
|
|
|
|
|
|
$self->compile_ast($node->first), |
230
|
|
|
|
|
|
|
$self->opcode($node->id) |
231
|
|
|
|
|
|
|
); |
232
|
|
|
|
|
|
|
# render_string can't be constant folded, because it depends on the |
233
|
|
|
|
|
|
|
# current vars |
234
|
997
|
0
|
33
|
|
|
185576
|
if ($Text::Xslate::Compiler::OPTIMIZE and $self->_code_is_literal(@code) && $node->id ne 'render_string' && $node->id ne 'find_file') { |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
235
|
0
|
|
|
|
|
0
|
$self->_fold_constants(\@code); |
236
|
|
|
|
|
|
|
} |
237
|
997
|
|
|
|
|
11803
|
return @code; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
else { |
240
|
70
|
|
|
|
|
492
|
return $self->SUPER::_generate_unary(@_); |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
sub is_unary { |
245
|
1067
|
|
|
1067
|
0
|
1428
|
my $self = shift; |
246
|
1067
|
|
|
|
|
5943
|
my ($id) = @_; |
247
|
|
|
|
|
|
|
|
248
|
4268
|
|
|
|
|
12353
|
my %unary = ( |
249
|
1067
|
|
|
|
|
2266
|
map { $_ => 1 } qw(builtin_is_array_ref builtin_is_hash_ref is_code_ref |
250
|
|
|
|
|
|
|
find_file) |
251
|
|
|
|
|
|
|
); |
252
|
|
|
|
|
|
|
|
253
|
1067
|
|
|
|
|
5306
|
return $unary{$id}; |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
sub _generate_array_length { |
257
|
70
|
|
|
70
|
|
2508
|
my $self = shift; |
258
|
70
|
|
|
|
|
137
|
my ($node) = @_; |
259
|
|
|
|
|
|
|
|
260
|
70
|
|
|
|
|
446
|
my $max_index = $self->parser->symbol('(max_index)')->clone( |
261
|
|
|
|
|
|
|
id => 'max_index', |
262
|
|
|
|
|
|
|
arity => 'unary', |
263
|
|
|
|
|
|
|
first => $node->first, |
264
|
|
|
|
|
|
|
); |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
return ( |
267
|
70
|
|
|
|
|
4293
|
$self->compile_ast($max_index), |
268
|
|
|
|
|
|
|
$self->opcode('move_to_sb'), |
269
|
|
|
|
|
|
|
$self->opcode('literal', 1), |
270
|
|
|
|
|
|
|
$self->opcode('add'), |
271
|
|
|
|
|
|
|
); |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
sub _generate_run_code { |
275
|
782
|
|
|
782
|
|
22761
|
my $self = shift; |
276
|
782
|
|
|
|
|
1272
|
my ($node) = @_; |
277
|
|
|
|
|
|
|
|
278
|
782
|
|
|
|
|
9102
|
my $to_render = $node->clone(arity => 'call'); |
279
|
|
|
|
|
|
|
|
280
|
782
|
100
|
|
|
|
24264
|
if ($node->third) { |
281
|
35
|
|
|
|
|
68
|
my ($open_tag, $close_tag) = @{ $node->third }; |
|
35
|
|
|
|
|
121
|
|
282
|
35
|
|
|
|
|
197
|
$to_render = $self->make_ternary( |
283
|
|
|
|
|
|
|
$self->parser->symbol('==')->clone( |
284
|
|
|
|
|
|
|
arity => 'binary', |
285
|
|
|
|
|
|
|
first => $close_tag->clone, |
286
|
|
|
|
|
|
|
second => $self->literal('}}'), |
287
|
|
|
|
|
|
|
), |
288
|
|
|
|
|
|
|
$to_render, |
289
|
|
|
|
|
|
|
$self->join('{{= ', $open_tag, ' ', $close_tag, ' =}}', $to_render) |
290
|
|
|
|
|
|
|
); |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
# XXX turn this into an opcode |
294
|
782
|
|
|
|
|
3408
|
my $render_string = $self->call( |
295
|
|
|
|
|
|
|
$node, |
296
|
|
|
|
|
|
|
'(render_string)', |
297
|
|
|
|
|
|
|
$to_render, |
298
|
|
|
|
|
|
|
$self->vars, |
299
|
|
|
|
|
|
|
); |
300
|
|
|
|
|
|
|
|
301
|
782
|
|
|
|
|
3916
|
return $self->compile_ast($render_string); |
302
|
|
|
|
|
|
|
} |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
sub _generate_new_vars { |
305
|
36
|
|
|
36
|
|
1064
|
my $self = shift; |
306
|
36
|
|
|
|
|
70
|
my ($node) = @_; |
307
|
|
|
|
|
|
|
|
308
|
36
|
|
|
|
|
347
|
my ($vars, $value, $i) = ($node->first, $node->second, $node->third); |
309
|
|
|
|
|
|
|
|
310
|
36
|
|
|
|
|
139
|
my $lvar_id = $self->lvar_id; |
311
|
36
|
|
|
|
|
151
|
local $self->{lvar_id} = $self->lvar_use(1); |
312
|
|
|
|
|
|
|
|
313
|
36
|
|
|
|
|
263
|
my @code; |
314
|
|
|
|
|
|
|
|
315
|
36
|
|
|
|
|
172
|
push @code, $self->compile_ast($value); |
316
|
36
|
|
|
|
|
16429
|
push @code, $self->opcode('save_to_lvar', $lvar_id); |
317
|
36
|
|
|
|
|
875
|
my $lvar_value = $value->clone(arity => 'lvar', id => $lvar_id); |
318
|
|
|
|
|
|
|
|
319
|
36
|
100
|
|
|
|
2446
|
if ($i) { |
320
|
35
|
|
|
|
|
317
|
my $value_at_index = $value->clone( |
321
|
|
|
|
|
|
|
arity => 'field', |
322
|
|
|
|
|
|
|
first => $value->clone, |
323
|
|
|
|
|
|
|
second => $i->clone, |
324
|
|
|
|
|
|
|
); |
325
|
|
|
|
|
|
|
|
326
|
35
|
|
|
|
|
2280
|
push @code, $self->compile_ast( |
327
|
|
|
|
|
|
|
$self->make_ternary( |
328
|
|
|
|
|
|
|
$self->is_array_ref($lvar_value->clone), |
329
|
|
|
|
|
|
|
$self->save_lvar( |
330
|
|
|
|
|
|
|
$lvar_id, |
331
|
|
|
|
|
|
|
$self->make_ternary( |
332
|
|
|
|
|
|
|
$self->is_hash_ref($value_at_index->clone), |
333
|
|
|
|
|
|
|
$self->merge_hash( |
334
|
|
|
|
|
|
|
$self->make_hash( |
335
|
|
|
|
|
|
|
$self->literal('.'), |
336
|
|
|
|
|
|
|
$value_at_index->clone, |
337
|
|
|
|
|
|
|
), |
338
|
|
|
|
|
|
|
$value_at_index->clone, |
339
|
|
|
|
|
|
|
), |
340
|
|
|
|
|
|
|
$self->make_hash( |
341
|
|
|
|
|
|
|
$self->literal('.'), |
342
|
|
|
|
|
|
|
$value_at_index->clone, |
343
|
|
|
|
|
|
|
), |
344
|
|
|
|
|
|
|
), |
345
|
|
|
|
|
|
|
), |
346
|
|
|
|
|
|
|
), |
347
|
|
|
|
|
|
|
); |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
else { |
350
|
1
|
|
|
|
|
3
|
push @code, $self->compile_ast( |
351
|
|
|
|
|
|
|
$self->make_ternary( |
352
|
|
|
|
|
|
|
$self->is_array_ref($lvar_value->clone), |
353
|
|
|
|
|
|
|
$self->save_lvar( |
354
|
|
|
|
|
|
|
$lvar_id, |
355
|
|
|
|
|
|
|
$self->make_hash( |
356
|
|
|
|
|
|
|
$self->literal('.'), |
357
|
|
|
|
|
|
|
$value->clone, |
358
|
|
|
|
|
|
|
), |
359
|
|
|
|
|
|
|
), |
360
|
|
|
|
|
|
|
), |
361
|
|
|
|
|
|
|
); |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
|
364
|
36
|
100
|
|
|
|
41156
|
push @code, $self->compile_ast( |
365
|
|
|
|
|
|
|
$self->save_lvar( |
366
|
|
|
|
|
|
|
$lvar_id, |
367
|
|
|
|
|
|
|
$self->make_ternary( |
368
|
|
|
|
|
|
|
$self->is_hash_ref($lvar_value->clone), |
369
|
|
|
|
|
|
|
$self->merge_hash( |
370
|
|
|
|
|
|
|
($i |
371
|
|
|
|
|
|
|
? ( |
372
|
|
|
|
|
|
|
$self->make_hash( |
373
|
|
|
|
|
|
|
$self->literal('@index'), $i->clone |
374
|
|
|
|
|
|
|
) |
375
|
|
|
|
|
|
|
) |
376
|
|
|
|
|
|
|
: ()), |
377
|
|
|
|
|
|
|
$vars->clone, |
378
|
|
|
|
|
|
|
$lvar_value->clone, |
379
|
|
|
|
|
|
|
$self->make_hash( |
380
|
|
|
|
|
|
|
$self->literal('..'), |
381
|
|
|
|
|
|
|
$vars->clone, |
382
|
|
|
|
|
|
|
), |
383
|
|
|
|
|
|
|
), |
384
|
|
|
|
|
|
|
$vars->clone, |
385
|
|
|
|
|
|
|
), |
386
|
|
|
|
|
|
|
), |
387
|
|
|
|
|
|
|
); |
388
|
|
|
|
|
|
|
|
389
|
36
|
|
|
|
|
22688
|
push @code, $self->opcode('load_lvar', $lvar_id); |
390
|
|
|
|
|
|
|
|
391
|
36
|
|
|
|
|
2379
|
return @code; |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
sub _generate_lvar { |
395
|
108
|
|
|
108
|
|
13920
|
my $self = shift; |
396
|
108
|
|
|
|
|
209
|
my ($node) = @_; |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
return ( |
399
|
108
|
|
|
|
|
824
|
$self->opcode('load_lvar', $node->id), |
400
|
|
|
|
|
|
|
); |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
sub _generate_save_lvar { |
404
|
72
|
|
|
72
|
|
3064
|
my $self = shift; |
405
|
72
|
|
|
|
|
118
|
my ($node) = @_; |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
return ( |
408
|
72
|
|
|
|
|
318
|
$self->compile_ast($node->first), |
409
|
|
|
|
|
|
|
$self->opcode('save_to_lvar', $node->id), |
410
|
|
|
|
|
|
|
); |
411
|
|
|
|
|
|
|
} |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
sub _generate_merge_hash { |
414
|
142
|
|
|
142
|
|
3328
|
my $self = shift; |
415
|
142
|
|
|
|
|
227
|
my ($node) = @_; |
416
|
|
|
|
|
|
|
|
417
|
142
|
|
|
|
|
559
|
my $lvar_id = $self->lvar_id; |
418
|
142
|
|
|
|
|
389
|
local $self->{lvar_id} = $self->lvar_use(1); |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
return ( |
421
|
142
|
|
|
|
|
1241
|
$self->compile_ast($node->first), |
422
|
|
|
|
|
|
|
$self->opcode('save_to_lvar', $lvar_id), |
423
|
|
|
|
|
|
|
$self->compile_ast($node->second), |
424
|
|
|
|
|
|
|
$self->opcode('move_to_sb'), |
425
|
|
|
|
|
|
|
$self->opcode('load_lvar', $lvar_id), |
426
|
|
|
|
|
|
|
$self->opcode('merge_hash'), |
427
|
|
|
|
|
|
|
); |
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
sub join { |
431
|
35
|
|
|
35
|
0
|
1957
|
my $self = shift; |
432
|
35
|
|
|
|
|
120
|
my (@args) = @_; |
433
|
|
|
|
|
|
|
|
434
|
35
|
|
|
|
|
73
|
@args = map { $self->literalize($_) } @args; |
|
210
|
|
|
|
|
5452
|
|
435
|
|
|
|
|
|
|
|
436
|
35
|
|
|
|
|
892
|
my $joined = shift @args; |
437
|
35
|
|
|
|
|
90
|
for my $arg (@args) { |
438
|
175
|
|
|
|
|
5859
|
$joined = $self->parser->symbol('~')->clone( |
439
|
|
|
|
|
|
|
arity => 'binary', |
440
|
|
|
|
|
|
|
first => $joined, |
441
|
|
|
|
|
|
|
second => $arg, |
442
|
|
|
|
|
|
|
); |
443
|
|
|
|
|
|
|
} |
444
|
|
|
|
|
|
|
|
445
|
35
|
|
|
|
|
1187
|
return $joined; |
446
|
|
|
|
|
|
|
} |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
sub literalize { |
449
|
210
|
|
|
210
|
0
|
426
|
my $self = shift; |
450
|
210
|
|
|
|
|
372
|
my ($val) = @_; |
451
|
|
|
|
|
|
|
|
452
|
210
|
100
|
|
|
|
843
|
return $val->clone if blessed($val); |
453
|
105
|
|
|
|
|
208
|
return $self->literal($val); |
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
sub call { |
457
|
815
|
|
|
815
|
0
|
33858
|
my $self = shift; |
458
|
815
|
|
|
|
|
2485
|
my ($node, $name, @args) = @_; |
459
|
|
|
|
|
|
|
|
460
|
815
|
|
|
|
|
4671
|
my $code = $self->parser->symbol('(name)')->clone( |
461
|
|
|
|
|
|
|
arity => 'name', |
462
|
|
|
|
|
|
|
id => $name, |
463
|
|
|
|
|
|
|
line => $node->line, |
464
|
|
|
|
|
|
|
); |
465
|
|
|
|
|
|
|
|
466
|
815
|
|
|
|
|
47002
|
return $self->parser->call($code, @args); |
467
|
|
|
|
|
|
|
} |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
sub make_ternary { |
470
|
1102
|
|
|
1102
|
0
|
43413
|
my $self = shift; |
471
|
1102
|
|
|
|
|
1861
|
my ($if, $then, $else) = @_; |
472
|
1102
|
|
|
|
|
6298
|
return $self->parser->symbol('?:')->clone( |
473
|
|
|
|
|
|
|
arity => 'if', |
474
|
|
|
|
|
|
|
first => $if, |
475
|
|
|
|
|
|
|
second => $then, |
476
|
|
|
|
|
|
|
third => $else, |
477
|
|
|
|
|
|
|
); |
478
|
|
|
|
|
|
|
} |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
sub vars { |
481
|
892
|
|
|
892
|
0
|
1235
|
my $self = shift; |
482
|
892
|
|
|
|
|
19543
|
return $self->parser->symbol('(vars)')->clone(arity => 'vars'); |
483
|
|
|
|
|
|
|
} |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
sub iterator_index { |
486
|
35
|
|
|
35
|
0
|
3954
|
my $self = shift; |
487
|
|
|
|
|
|
|
|
488
|
35
|
|
|
|
|
194
|
return $self->parser->symbol('(iterator)')->clone( |
489
|
|
|
|
|
|
|
arity => 'iterator', |
490
|
|
|
|
|
|
|
id => '$~(loop_var)', |
491
|
|
|
|
|
|
|
first => $self->parser->symbol('(loop_var)')->clone, |
492
|
|
|
|
|
|
|
), |
493
|
|
|
|
|
|
|
} |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
sub check_lambda { |
496
|
747
|
|
|
747
|
0
|
1227
|
my $self = shift; |
497
|
747
|
|
|
|
|
1281
|
my ($var) = @_; |
498
|
|
|
|
|
|
|
|
499
|
747
|
|
|
|
|
2469
|
return $self->make_ternary( |
500
|
|
|
|
|
|
|
$self->is_code_ref($var->clone), |
501
|
|
|
|
|
|
|
$self->run_code($var->clone), |
502
|
|
|
|
|
|
|
$var, |
503
|
|
|
|
|
|
|
); |
504
|
|
|
|
|
|
|
} |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
sub is_array_ref { |
507
|
141
|
|
|
141
|
0
|
4915
|
my $self = shift; |
508
|
141
|
|
|
|
|
331
|
my ($var) = @_; |
509
|
|
|
|
|
|
|
|
510
|
141
|
|
|
|
|
712
|
return $self->parser->symbol('(is_array_ref)')->clone( |
511
|
|
|
|
|
|
|
id => 'builtin_is_array_ref', |
512
|
|
|
|
|
|
|
arity => 'unary', |
513
|
|
|
|
|
|
|
first => $var, |
514
|
|
|
|
|
|
|
); |
515
|
|
|
|
|
|
|
} |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
sub is_hash_ref { |
518
|
71
|
|
|
71
|
0
|
3120
|
my $self = shift; |
519
|
71
|
|
|
|
|
139
|
my ($var) = @_; |
520
|
|
|
|
|
|
|
|
521
|
71
|
|
|
|
|
399
|
return $self->parser->symbol('(is_hash_ref)')->clone( |
522
|
|
|
|
|
|
|
id => 'builtin_is_hash_ref', |
523
|
|
|
|
|
|
|
arity => 'unary', |
524
|
|
|
|
|
|
|
first => $var, |
525
|
|
|
|
|
|
|
); |
526
|
|
|
|
|
|
|
} |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
sub is_code_ref { |
529
|
782
|
|
|
782
|
0
|
18345
|
my $self = shift; |
530
|
782
|
|
|
|
|
1098
|
my ($var) = @_; |
531
|
|
|
|
|
|
|
|
532
|
782
|
|
|
|
|
4960
|
return $self->parser->symbol('(is_code_ref)')->clone( |
533
|
|
|
|
|
|
|
id => 'is_code_ref', |
534
|
|
|
|
|
|
|
arity => 'unary', |
535
|
|
|
|
|
|
|
first => $var, |
536
|
|
|
|
|
|
|
); |
537
|
|
|
|
|
|
|
} |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
sub make_array { |
540
|
70
|
|
|
70
|
0
|
2434
|
my $self = shift; |
541
|
70
|
|
|
|
|
150
|
my (@contents) = @_; |
542
|
|
|
|
|
|
|
|
543
|
70
|
|
|
|
|
359
|
return $self->parser->symbol('[')->clone( |
544
|
|
|
|
|
|
|
arity => 'composer', |
545
|
|
|
|
|
|
|
first => \@contents, |
546
|
|
|
|
|
|
|
); |
547
|
|
|
|
|
|
|
} |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
sub make_hash { |
550
|
183
|
|
|
183
|
0
|
8548
|
my $self = shift; |
551
|
183
|
|
|
|
|
439
|
my (@contents) = @_; |
552
|
|
|
|
|
|
|
|
553
|
183
|
|
|
|
|
908
|
return $self->parser->symbol('{')->clone( |
554
|
|
|
|
|
|
|
arity => 'composer', |
555
|
|
|
|
|
|
|
first => \@contents, |
556
|
|
|
|
|
|
|
); |
557
|
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
sub is_falsy { |
560
|
70
|
|
|
70
|
0
|
1483
|
my $self = shift; |
561
|
70
|
|
|
|
|
108
|
my ($node) = @_; |
562
|
|
|
|
|
|
|
|
563
|
70
|
|
|
|
|
237
|
return $self->not( |
564
|
|
|
|
|
|
|
$self->make_ternary( |
565
|
|
|
|
|
|
|
$self->is_array_ref($node->clone), |
566
|
|
|
|
|
|
|
$self->array_length($node->clone), |
567
|
|
|
|
|
|
|
$node |
568
|
|
|
|
|
|
|
) |
569
|
|
|
|
|
|
|
); |
570
|
|
|
|
|
|
|
} |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
sub not { |
573
|
70
|
|
|
70
|
0
|
5849
|
my $self = shift; |
574
|
70
|
|
|
|
|
113
|
my ($node) = @_; |
575
|
|
|
|
|
|
|
|
576
|
70
|
|
|
|
|
311
|
return $self->parser->symbol('!')->clone( |
577
|
|
|
|
|
|
|
arity => 'unary', |
578
|
|
|
|
|
|
|
first => $node, |
579
|
|
|
|
|
|
|
); |
580
|
|
|
|
|
|
|
} |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
sub array_length { |
583
|
70
|
|
|
70
|
0
|
4077
|
my $self = shift; |
584
|
70
|
|
|
|
|
124
|
my ($node) = @_; |
585
|
|
|
|
|
|
|
|
586
|
70
|
|
|
|
|
321
|
return $self->parser->symbol('(array_length)')->clone( |
587
|
|
|
|
|
|
|
arity => 'array_length', |
588
|
|
|
|
|
|
|
first => $node, |
589
|
|
|
|
|
|
|
); |
590
|
|
|
|
|
|
|
} |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
sub run_code { |
593
|
782
|
|
|
782
|
0
|
52482
|
my $self = shift; |
594
|
782
|
|
|
|
|
1475
|
my ($code, $raw_text, $open_tag, $close_tag) = @_; |
595
|
|
|
|
|
|
|
|
596
|
782
|
100
|
|
|
|
4168
|
return $self->parser->symbol('(run_code)')->clone( |
597
|
|
|
|
|
|
|
arity => 'run_code', |
598
|
|
|
|
|
|
|
first => $code, |
599
|
|
|
|
|
|
|
(@_ > 1 |
600
|
|
|
|
|
|
|
? (second => [ $raw_text ], third => [ $open_tag, $close_tag ]) |
601
|
|
|
|
|
|
|
: (second => [])), |
602
|
|
|
|
|
|
|
); |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
sub new_vars { |
606
|
36
|
|
|
36
|
0
|
2485
|
my $self = shift; |
607
|
36
|
|
|
|
|
68
|
my ($value, $i) = @_; |
608
|
|
|
|
|
|
|
|
609
|
36
|
|
|
|
|
139
|
return $value->clone( |
610
|
|
|
|
|
|
|
arity => 'new_vars', |
611
|
|
|
|
|
|
|
first => $self->vars, |
612
|
|
|
|
|
|
|
second => $value, |
613
|
|
|
|
|
|
|
third => $i, |
614
|
|
|
|
|
|
|
); |
615
|
|
|
|
|
|
|
} |
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
sub save_lvar { |
618
|
72
|
|
|
72
|
0
|
2620
|
my $self = shift; |
619
|
72
|
|
|
|
|
121
|
my ($id, $value) = @_; |
620
|
|
|
|
|
|
|
|
621
|
72
|
|
|
|
|
243
|
return $value->clone( |
622
|
|
|
|
|
|
|
arity => 'save_lvar', |
623
|
|
|
|
|
|
|
id => $id, |
624
|
|
|
|
|
|
|
first => $value, |
625
|
|
|
|
|
|
|
); |
626
|
|
|
|
|
|
|
} |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
sub merge_hash { |
629
|
71
|
|
|
71
|
0
|
3297
|
my $self = shift; |
630
|
71
|
|
|
|
|
166
|
my (@hashes) = @_; |
631
|
|
|
|
|
|
|
|
632
|
71
|
|
|
|
|
136
|
my $merged = shift @hashes; |
633
|
71
|
|
|
|
|
190
|
for my $hash (@hashes) { |
634
|
142
|
|
|
|
|
2268
|
$merged = $self->merge_single_hash($merged, $hash); |
635
|
|
|
|
|
|
|
} |
636
|
|
|
|
|
|
|
|
637
|
71
|
|
|
|
|
2262
|
return $merged; |
638
|
|
|
|
|
|
|
} |
639
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
sub merge_single_hash { |
641
|
142
|
|
|
142
|
0
|
188
|
my $self = shift; |
642
|
142
|
|
|
|
|
229
|
my ($left, $right) = @_; |
643
|
|
|
|
|
|
|
|
644
|
142
|
|
|
|
|
436
|
return $left->clone( |
645
|
|
|
|
|
|
|
arity => 'merge_hash', |
646
|
|
|
|
|
|
|
first => $left, |
647
|
|
|
|
|
|
|
second => $right, |
648
|
|
|
|
|
|
|
); |
649
|
|
|
|
|
|
|
} |
650
|
|
|
|
|
|
|
|
651
|
381
|
|
|
381
|
0
|
16173
|
sub literal { shift->parser->literal(@_) } |
652
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
654
|
12
|
|
|
12
|
|
136
|
no Mouse; |
|
12
|
|
|
|
|
26
|
|
|
12
|
|
|
|
|
104
|
|
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
=for Pod::Coverage |
657
|
|
|
|
|
|
|
define_helper |
658
|
|
|
|
|
|
|
find_file |
659
|
|
|
|
|
|
|
is_unary |
660
|
|
|
|
|
|
|
join |
661
|
|
|
|
|
|
|
literalize |
662
|
|
|
|
|
|
|
call |
663
|
|
|
|
|
|
|
make_ternary |
664
|
|
|
|
|
|
|
vars |
665
|
|
|
|
|
|
|
iterator_index |
666
|
|
|
|
|
|
|
check_lambda |
667
|
|
|
|
|
|
|
is_array_ref |
668
|
|
|
|
|
|
|
is_hash_ref |
669
|
|
|
|
|
|
|
is_code_ref |
670
|
|
|
|
|
|
|
make_array |
671
|
|
|
|
|
|
|
make_hash |
672
|
|
|
|
|
|
|
is_falsy |
673
|
|
|
|
|
|
|
not |
674
|
|
|
|
|
|
|
array_length |
675
|
|
|
|
|
|
|
run_code |
676
|
|
|
|
|
|
|
new_vars |
677
|
|
|
|
|
|
|
save_lvar |
678
|
|
|
|
|
|
|
merge_hash |
679
|
|
|
|
|
|
|
merge_single_hash |
680
|
|
|
|
|
|
|
literal |
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
=cut |
683
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
1; |