File Coverage

blib/lib/Text/Xslate/PP/Opcode.pm
Criterion Covered Total %
statement 43 319 13.4
branch 1 42 2.3
condition 0 2 0.0
subroutine 15 86 17.4
pod 0 75 0.0
total 59 524 11.2


line stmt bran cond sub pod time code
1             package Text::Xslate::PP::Opcode;
2 1     1   4 use Mouse;
  1         2  
  1         7  
3             extends qw(Text::Xslate::PP::State);
4              
5             our $VERSION = '3.4.0';
6              
7 1     1   339 use Carp ();
  1         1  
  1         11  
8 1     1   4 use Scalar::Util ();
  1         0  
  1         12  
9              
10 1     1   3 use Text::Xslate::PP;
  1         1  
  1         15  
11 1     1   2 use Text::Xslate::PP::Const;
  1         2  
  1         132  
12 1     1   380 use Text::Xslate::PP::Method;
  1         1  
  1         31  
13 1         185 use Text::Xslate::Util qw(
14             p neat
15             mark_raw unmark_raw html_escape uri_escape
16             $DEBUG
17 1     1   4 );
  1         1  
18              
19 1     1   5 use constant _DUMP_PP => scalar($DEBUG =~ /\b dump=pp \b/xms);
  1         1  
  1         68  
20              
21 1     1   5 no warnings 'recursion';
  1         2  
  1         4213  
22              
23             if(!Text::Xslate::PP::_PP_ERROR_VERBOSE()) {
24             our @CARP_NOT = qw(
25             Text::Xslate
26             );
27             }
28             our $_current_frame;
29              
30              
31             #
32             #
33             #
34              
35             sub op_noop {
36 1     1 0 6 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
37             }
38              
39              
40             sub op_move_to_sb {
41 0     0 0 0 $_[0]->{sb} = $_[0]->{sa};
42 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
43             }
44              
45             sub op_move_from_sb {
46 0     0 0 0 $_[0]->{sa} = $_[0]->{sb};
47 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
48             }
49              
50             sub op_save_to_lvar {
51 0     0 0 0 tx_access_lvar( $_[0], $_[0]->op_arg, $_[0]->{sa} );
52 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
53             }
54              
55             sub op_load_lvar {
56 0     0 0 0 $_[0]->{sa} = tx_access_lvar( $_[0], $_[0]->op_arg );
57 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
58             }
59              
60             sub op_load_lvar_to_sb {
61 0     0 0 0 $_[0]->{sb} = tx_access_lvar( $_[0], $_[0]->op_arg );
62 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
63             }
64              
65             sub op_localize_s {
66 0     0 0 0 my($st) = @_;
67 0         0 my $key = $st->op_arg;
68 0         0 my $newval = $st->{sa};
69 0         0 $st->localize($key, $newval);
70              
71 0         0 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
72             }
73              
74             sub op_localize_vars {
75 0     0 0 0 my($st) = @_;
76 0         0 my $new_vars = $st->{sa};
77 0         0 my $old_vars = $st->vars;
78              
79 0 0       0 if(ref($new_vars) ne 'HASH') {
80 0         0 $st->warn(undef, "Variable map must be a HASH reference");
81             }
82              
83 0         0 push @{ $st->{local_stack} }, bless sub {
84 0     0   0 $st->vars($old_vars);
85 0         0 return;
86 0         0 }, 'Text::Xslate::PP::Guard';
87              
88 0         0 $st->vars($new_vars);
89              
90 0         0 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
91             }
92              
93             sub op_push {
94 0     0 0 0 push @{ $_[0]->{ SP }->[ -1 ] }, $_[0]->{sa};
  0         0  
95 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
96             }
97              
98              
99             sub op_pushmark {
100 0     0 0 0 push @{ $_[0]->{ SP } }, [];
  0         0  
101 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
102             }
103              
104              
105             sub op_nil {
106 0     0 0 0 $_[0]->{sa} = undef;
107 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
108             }
109              
110             sub op_vars {
111 0     0 0 0 $_[0]->{sa} = $_[0]->{vars};
112              
113 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
114             }
115              
116             sub op_literal {
117 0     0 0 0 $_[0]->{sa} = $_[0]->op_arg;
118 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
119             }
120              
121              
122             sub op_literal_i {
123 0     0 0 0 $_[0]->{sa} = $_[0]->op_arg;
124 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
125             }
126              
127              
128             sub op_fetch_s {
129 1     1 0 4 $_[0]->{sa} = $_[0]->{vars}->{ $_[0]->op_arg };
130 1         3 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
131             }
132              
133             sub op_fetch_field {
134 0     0 0 0 my($st) = @_;
135 0         0 my $var = $st->{sb};
136 0         0 my $key = $st->{sa};
137 0         0 $st->{sa} = $st->fetch($var, $key);
138 0         0 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
139             }
140              
141              
142             sub op_fetch_field_s {
143 0     0 0 0 my($st) = @_;
144 0         0 my $var = $st->{sa};
145 0         0 my $key = $st->op_arg;
146 0         0 $st->{sa} = $st->fetch($var, $key);
147 0         0 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
148             }
149              
150              
151             sub op_print {
152 1     1 0 2 my($st) = @_;
153 1         4 $st->print($st->{sa});
154 1         2 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
155             }
156              
157              
158             sub op_print_raw {
159 0     0 0 0 my($st) = @_;
160 0 0       0 if(defined $st->{sa}) {
161 0         0 $st->{ output } .= $st->{sa};
162             }
163             else {
164 0         0 $st->warn( undef, "Use of nil to print" );
165             }
166 0         0 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
167             }
168              
169              
170             sub op_print_raw_s {
171 2     2 0 9 $_[0]->{ output } .= $_[0]->op_arg;
172 2         5 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
173             }
174              
175              
176             sub op_include {
177 0     0 0 0 my($st) = @_;
178 0         0 my $child = Text::Xslate::PP::tx_load_template( $st->engine, $st->{sa}, 1 );
179 0         0 $st->push_frame('include', undef);
180 0         0 my $output = Text::Xslate::PP::tx_execute( $child, $st->{vars} );
181 0         0 $st->pop_frame(0);
182 0         0 $st->{output} .= $output;
183 0         0 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
184             }
185              
186             sub op_find_file {
187 0     0 0 0 $_[0]->{sa} = eval { $_[0]->engine->find_file($_[0]->{sa}); 1 };
  0         0  
  0         0  
188 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
189             }
190              
191             sub op_suffix {
192 0     0 0 0 $_[0]->{sa} = $_[0]->engine->{suffix};
193 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
194             }
195              
196             sub op_for_start {
197 0     0 0 0 my($st) = @_;
198 0         0 my $id = $st->op_arg;
199 0         0 my $ar = Text::Xslate::PP::tx_check_itr_ar($st, $st->{sa});
200              
201             #tx_access_lvar( $st, $id + TXfor_ITEM, undef );
202 0         0 tx_access_lvar( $st, $id + TXfor_ITER, -1 );
203 0         0 tx_access_lvar( $st, $id + TXfor_ARRAY, $ar );
204              
205 0         0 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
206             }
207              
208              
209             sub op_for_iter {
210 0     0 0 0 my($st) = @_;
211 0         0 my $id = $st->{sa};
212 0         0 my $av = tx_access_lvar( $st, $id + TXfor_ARRAY );
213              
214 0 0       0 if(defined $av) {
215 0         0 my $i = tx_access_lvar( $st, $id + TXfor_ITER );
216 0 0       0 $av = [ $av ] unless ref $av;
217 0 0       0 if ( ++$i < scalar(@{ $av }) ) {
  0         0  
218 0         0 tx_access_lvar( $st, $id + TXfor_ITEM, $av->[ $i ] );
219 0         0 tx_access_lvar( $st, $id + TXfor_ITER, $i );
220 0         0 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
221             }
222             else {
223             # finish the loop
224 0         0 $st->{sa} = ( $i > 0 ); # for 'for-else' block
225 0         0 tx_access_lvar( $st, $id + TXfor_ITEM, undef );
226 0         0 tx_access_lvar( $st, $id + TXfor_ITER, undef );
227 0         0 tx_access_lvar( $st, $id + TXfor_ARRAY, undef );
228             }
229             }
230              
231             # finish
232 0         0 $st->{ pc } = $st->op_arg;
233 0         0 goto $st->{ code }->[ $st->{ pc } ]->{ exec_code };
234             }
235              
236              
237             sub op_add {
238 0     0 0 0 $_[0]->{sa} = $_[0]->{sb} + $_[0]->{sa};
239 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
240             }
241              
242              
243             sub op_sub {
244 0     0 0 0 $_[0]->{sa} = $_[0]->{sb} - $_[0]->{sa};
245 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
246             }
247              
248              
249             sub op_mul {
250 0     0 0 0 $_[0]->{sa} = $_[0]->{sb} * $_[0]->{sa};
251 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
252             }
253              
254              
255             sub op_div {
256 0     0 0 0 $_[0]->{sa} = $_[0]->{sb} / $_[0]->{sa};
257 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
258             }
259              
260              
261             sub op_mod {
262 0     0 0 0 my($st) = @_;
263 0         0 my $lhs = int $st->{sb};
264 0         0 my $rhs = int $st->{sa};
265 0 0       0 if($rhs == 0) {
266 0         0 $st->error(undef, "Illegal modulus zero");
267 0         0 $st->{sa} = 'NaN';
268             }
269             else {
270 0         0 $st->{sa} = $lhs % $rhs;
271             }
272 0         0 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
273             }
274              
275              
276             sub op_concat {
277 0     0 0 0 my($st) = @_;
278 0         0 $st->{sa} = Text::Xslate::PP::tx_concat($st->{sb}, $st->{sa});
279 0         0 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
280             }
281              
282             sub op_repeat {
283 0     0 0 0 my($st) = @_;
284 0         0 $st->{sa} = Text::Xslate::PP::tx_repeat($st->{sb}, $st->{sa});
285 0         0 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
286             }
287              
288             sub op_bitor {
289 0     0 0 0 $_[0]->{sa} = int($_[0]->{sb}) | int($_[0]->{sa});
290 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
291             }
292              
293             sub op_bitand {
294 0     0 0 0 $_[0]->{sa} = int($_[0]->{sb}) & int($_[0]->{sa});
295 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
296             }
297              
298             sub op_bitxor {
299 0     0 0 0 $_[0]->{sa} = int($_[0]->{sb}) ^ int($_[0]->{sa});
300 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
301             }
302              
303             sub op_bitneg {
304 0     0 0 0 $_[0]->{sa} = ~int($_[0]->{sa});
305 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
306             }
307              
308              
309              
310             sub op_and {
311 0 0   0 0 0 if ( $_[0]->{sa} ) {
312 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
313             }
314             else {
315 0         0 $_[0]->{ pc } = $_[0]->op_arg;
316 0         0 goto $_[0]->{ code }->[ $_[0]->{ pc } ]->{ exec_code };
317             }
318             }
319              
320              
321             sub op_dand {
322 0 0   0 0 0 if ( defined $_[0]->{sa} ) {
323 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
324             }
325             else {
326 0         0 $_[0]->{ pc } = $_[0]->op_arg;
327 0         0 goto $_[0]->{ code }->[ $_[0]->{ pc } ]->{ exec_code };
328             }
329             }
330              
331              
332             sub op_or {
333 0 0   0 0 0 if ( ! $_[0]->{sa} ) {
334 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
335             }
336             else {
337 0         0 $_[0]->{ pc } = $_[0]->op_arg;
338 0         0 goto $_[0]->{ code }->[ $_[0]->{ pc } ]->{ exec_code };
339             }
340             }
341              
342              
343             sub op_dor {
344 0     0 0 0 my $sv = $_[0]->{sa};
345 0 0       0 if ( defined $sv ) {
346 0         0 $_[0]->{ pc } = $_[0]->op_arg;
347 0         0 goto $_[0]->{ code }->[ $_[0]->{ pc } ]->{ exec_code };
348             }
349             else {
350 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
351             }
352              
353             }
354              
355             sub op_not {
356 0     0 0 0 $_[0]->{sa} = ! $_[0]->{sa};
357 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
358             }
359              
360             sub op_minus {
361 0     0 0 0 $_[0]->{sa} = -$_[0]->{sa};
362 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
363             }
364              
365             sub op_max_index {
366 0     0 0 0 $_[0]->{sa} = scalar(@{ $_[0]->{sa} }) - 1;
  0         0  
367 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
368             }
369              
370             sub op_builtin_mark_raw {
371 0     0 0 0 $_[0]->{sa} = mark_raw($_[0]->{sa});
372 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
373             }
374              
375             sub op_builtin_unmark_raw {
376 0     0 0 0 $_[0]->{sa} = unmark_raw($_[0]->{sa});
377 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
378             }
379              
380             sub op_builtin_html_escape {
381 0     0 0 0 $_[0]->{sa} = html_escape($_[0]->{sa});
382 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
383             }
384              
385             sub op_builtin_uri_escape {
386 0     0 0 0 $_[0]->{sa} = uri_escape($_[0]->{sa});
387 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
388             }
389              
390             sub op_builtin_is_array_ref {
391 0     0 0 0 $_[0]->{sa} = Text::Xslate::Util::is_array_ref($_[0]->{sa});
392 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
393             }
394              
395             sub op_builtin_is_hash_ref {
396 0     0 0 0 $_[0]->{sa} = Text::Xslate::Util::is_hash_ref($_[0]->{sa});
397 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
398             }
399              
400             sub op_is_code_ref {
401 0     0 0 0 $_[0]->{sa} = Text::Xslate::Util::is_code_ref($_[0]->{sa});
402 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
403             }
404              
405             sub op_match {
406 0     0 0 0 $_[0]->{sa} = Text::Xslate::PP::tx_match($_[0]->{sb}, $_[0]->{sa});
407 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
408             }
409              
410             sub op_eq {
411 0     0 0 0 $_[0]->{sa} = Text::Xslate::PP::tx_sv_eq($_[0]->{sb}, $_[0]->{sa});
412 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
413             }
414              
415              
416             sub op_ne {
417 0     0 0 0 $_[0]->{sa} = !Text::Xslate::PP::tx_sv_eq($_[0]->{sb}, $_[0]->{sa});
418 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
419             }
420              
421              
422             sub op_lt {
423 0     0 0 0 $_[0]->{sa} = $_[0]->{sb} < $_[0]->{sa};
424 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
425             }
426              
427             sub op_le {
428 0     0 0 0 $_[0]->{sa} = $_[0]->{sb} <= $_[0]->{sa};
429 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
430             }
431              
432             sub op_gt {
433 0     0 0 0 $_[0]->{sa} = $_[0]->{sb} > $_[0]->{sa};
434 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
435             }
436              
437             sub op_ge {
438 0     0 0 0 $_[0]->{sa} = $_[0]->{sb} >= $_[0]->{sa};
439 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
440             }
441              
442             sub op_ncmp {
443 0     0 0 0 $_[0]->{sa} = $_[0]->{sb} <=> $_[0]->{sa};
444 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
445             }
446             sub op_scmp {
447 0     0 0 0 $_[0]->{sa} = $_[0]->{sb} cmp $_[0]->{sa};
448 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
449             }
450              
451             sub op_range {
452 0     0 0 0 my($self) = @_;
453 0         0 push @{ $self->{ SP }->[ -1 ] }, ($self->{sb} .. $self->{sa});
  0         0  
454 0         0 goto $self->{ code }->[ ++$self->{ pc } ]->{ exec_code };
455             }
456              
457             sub op_fetch_symbol {
458 0     0 0 0 my($st) = @_;
459 0         0 my $name = $st->op_arg;
460 0         0 $st->{sa} = $st->fetch_symbol($name);
461              
462 0         0 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
463             }
464              
465             sub tx_macro_enter {
466 0     0 0 0 my($st, $macro, $retaddr) = @_;
467 0         0 my $name = $macro->name;
468 0         0 my $addr = $macro->addr;
469 0         0 my $nargs = $macro->nargs;
470 0         0 my $outer = $macro->outer;
471 0         0 my $args = pop @{ $st->{SP} };
  0         0  
472              
473 0         0 print STDERR " " x $st->current_frame, "tx_macro_enter($name) to $retaddr\n" if _DUMP_PP;
474              
475 0 0       0 if(@{$args} != $nargs) {
  0         0  
476             $st->error(undef, "Wrong number of arguments for %s (%d %s %d)",
477 0 0       0 $name, scalar(@{$args}), scalar(@{$args}) > $nargs ? '>' : '<', $nargs);
  0         0  
  0         0  
478 0         0 $st->{ sa } = undef;
479 0         0 $st->{ pc }++;
480 0         0 return;
481             }
482              
483 0         0 my $cframe = $st->push_frame($name, $retaddr);
484              
485 0         0 $cframe->[ TXframe_OUTPUT ] = $st->{ output };
486              
487 0         0 $st->{ output } = '';
488              
489 0         0 my $i = 0;
490 0 0       0 if($outer > 0) {
491             # copies lexical variables from the old frame to the new one
492 0         0 my $oframe = $st->frame->[ $st->current_frame - 1 ];
493 0         0 for(; $i < $outer; $i++) {
494 0         0 my $real_ix = $i + TXframe_START_LVAR;
495 0         0 $cframe->[$real_ix] = $oframe->[$real_ix];
496             }
497             }
498              
499 0         0 for my $val (@{$args}) {
  0         0  
500 0         0 tx_access_lvar( $st, $i++, $val );
501             }
502              
503 0         0 $st->{ pc } = $addr;
504 0 0       0 if($st->{code}->[$addr]->{opname} ne 'macro_begin') {
505 0         0 Carp::croak("Oops: entering non-macros: ", p($st->{code}->[$addr]));
506             }
507 0         0 return;
508             }
509              
510             sub op_macro_end {
511 0     0 0 0 my($st) = @_;
512              
513 0         0 my $top = $st->frame->[ $st->current_frame ];
514 0         0 printf STDERR "%stx_macro_end(%s)]\n", ' ' x $st->current_frame - 1, $top->[ TXframe_NAME ] if _DUMP_PP;
515              
516 0         0 $st->{sa} = mark_raw( $st->{ output } );
517 0         0 $st->pop_frame(1);
518              
519 0         0 $st->{ pc } = $top->[ TXframe_RETADDR ];
520 0         0 goto $st->{ code }->[ $st->{ pc } ]->{ exec_code };
521             }
522              
523             sub op_funcall {
524 0     0 0 0 my($st) = @_;
525 0         0 my $func = $st->{sa};
526 0 0       0 if(ref $func eq TXt_MACRO) {
527 0         0 tx_macro_enter($st, $func, $st->{ pc } + 1);
528 0         0 goto $st->{ code }->[ $st->{ pc } ]->{ exec_code };
529             }
530             else {
531 0         0 $st->{sa} = tx_funcall( $st, $func );
532 0         0 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
533             }
534             }
535              
536             sub op_methodcall_s {
537 0     0 0 0 my($st) = @_;
538             $st->{sa} = Text::Xslate::PP::Method::tx_methodcall(
539 0         0 $st, undef, $st->op_arg, @{ pop @{ $st->{SP} } });
  0         0  
  0         0  
540 0         0 goto $st->{ code }->[ ++$st->{ pc } ]->{ exec_code };
541             }
542              
543             sub op_make_array {
544 0     0 0 0 my $args = pop @{ $_[0]->{SP} };
  0         0  
545 0         0 $_[0]->{sa} = $args;
546 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
547             }
548              
549             sub op_make_hash {
550 0     0 0 0 my $args = pop @{ $_[0]->{SP} };
  0         0  
551 0         0 $_[0]->{sa} = { @{$args} };
  0         0  
552 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
553             }
554              
555             sub op_merge_hash {
556 0     0 0 0 $_[0]->{sa} = Text::Xslate::Util::merge_hash($_[0]->{sa}, $_[0]->{sb});
557 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
558             }
559              
560              
561             sub op_enter {
562 0   0 0 0 0 push @{$_[0]->{save_local_stack} ||= []}, delete $_[0]->{local_stack};
  0         0  
563              
564 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
565             }
566              
567             sub op_leave {
568 0     0 0 0 $_[0]->{local_stack} = pop @{$_[0]->{save_local_stack}};
  0         0  
569              
570 0         0 goto $_[0]->{ code }->[ ++$_[0]->{ pc } ]->{ exec_code };
571             }
572              
573             sub op_goto {
574 0     0 0 0 $_[0]->{ pc } = $_[0]->op_arg;
575 0         0 goto $_[0]->{ code }->[ $_[0]->{ pc } ]->{ exec_code };
576             }
577              
578             sub op_end {
579 1     1 0 2 my($st) = @_;
580 1         1 printf STDERR "op_end at %d\n", $st->{pc} if _DUMP_PP;
581 1         3 $st->{ pc } = $st->code_len;
582              
583 1 50       3 if($st->current_frame != 0) {
584             #Carp::croak("Oops: broken stack frame:" . p($st->frame));
585             }
586 1         2 return;
587             }
588              
589             sub op_depend; *op_depend = \&op_noop;
590             sub op_macro_begin; *op_macro_begin = \&op_noop;
591             sub op_macro_nargs; *op_macro_nargs = \&op_noop;
592             sub op_macro_outer; *op_macro_outer = \&op_noop;
593             sub op_set_opinfo; *op_set_opinfo = \&op_noop;
594             sub op_super; *op_super = \&op_noop;
595              
596             #
597             # INTERNAL COMMON FUNCTIONS
598             #
599              
600             sub tx_access_lvar {
601 0 0   0 0   return $_[0]->pad->[ $_[1] + TXframe_START_LVAR ] if @_ == 2;
602 0           $_[0]->pad->[ $_[1] + TXframe_START_LVAR ] = $_[2];
603             }
604              
605              
606             sub tx_funcall {
607 0     0 0   my ( $st, $proc ) = @_;
608 0           my ( @args ) = @{ pop @{ $st->{ SP } } };
  0            
  0            
609 0           my $ret;
610              
611 0 0         if(!defined $proc) {
612 0           my $c = $st->{code}->[ $st->{pc} - 1 ];
613             $st->error( undef, "Undefined function%s is called",
614 0 0         $c->{ opname } eq 'fetch_s' ? " $c->{arg}()" : ""
615             );
616             }
617             else {
618 0           $ret = eval { $proc->( @args ) };
  0            
619 0 0         $st->error( undef, "%s", $@) if $@;
620             }
621              
622 0           return $ret;
623             }
624              
625             sub proccall {
626 0     0 0   my($st, $proc) = @_;
627 0 0         if(ref $proc eq TXt_MACRO) {
628 0           local $st->{pc} = $st->{pc};
629 0           tx_macro_enter($st, $proc, $st->{code_len});
630 0           $st->{code}->[ $st->{pc} ]->{ exec_code }->( $st );
631 0           return $st->{sa};
632             }
633             else {
634 0           return tx_funcall($st, $proc);
635             }
636             }
637              
638 1     1   11 no Mouse;
  1         1  
  1         6  
639             __PACKAGE__->meta->make_immutable();
640             __END__