NAME
Text::Xslate::PP::Booster - Text::Xslate code generator for pure Perl
SYNOPSIS
# If you want to check created codes, you can use it directly.
use Text::Xslate::PP;
use Text::Xslate::PP::Booster;
my $tx = Text::Xslate->new();
my $booster = Text::Xslate::PP::Booster->new();
my $optext = q{<: $value :>};
my $code = $booster->opcode_to_perlcode_string( $tx->compile( $optext ) );
my $coderef = $booster->opcode_to_perlcode( $tx->compile( $optext ) );
# $coderef takes a Text::Xslate::PP::State object
DESCRIPTION
This module is another pure Perl engine, which is much faster than Text::Xslate::PP::Opcode, but might be less stable.
This engine is enabled by $ENV{ENV}='pp=booster'
.
APIs
new
Constructor.
$booster = Text::Xslate::PP::Booster->new();
opcode_to_perlcode
Takes a virtual machine code created by Text::Xslate::Compiler, and returns a code reference.
$coderef = $booster->opcode_to_perlcode( $ops );
The code reference takes Text::Xslate::PP::State
object in Xslate runtime processes. Don't execute this code reference directly.
opcode_to_perlcode_string
Takes a virtual machine code created by Text::Xslate::Compiler
, and returns a perl subroutine code text.
$str = $booster->opcode_to_perlcode_string( $ops );
ABOUT BOOST CODE
Text::Xslate::PP::Booster
creates a code reference from a virtual machine code.
$tx->render_string( <<'CODE', {} );
: macro foo -> $arg {
Hello <:= $arg :>!
: }
: foo($value)
CODE
Firstly the template data is converted to opcodes:
pushmark
fetch_s "value"
push
macro "foo"
macrocall
print
end
macro_begin "foo"
print_raw_s " Hello "
fetch_lvar 0
print
print_raw_s "!\n"
macro_end
And the booster converted them into a perl subroutine code (you can get that code by XSLATE=dump=pp
).
sub {
no warnings 'recursion';
my ( $st ) = @_;
my ( $sv, $pad, %macro, $depth );
my $output = q{};
my $vars = $st->{ vars };
$st->{pad} = $pad = [ [ ] ];
# macro
$macro{"foo"} = $st->{ booster_macro }->{"foo"} ||= sub {
my ( $st, $pad, $f_l ) = @_;
my $vars = $st->{ vars };
my $mobj = $st->symbol->{ "foo" };
my $output = q{};
if ( @{$pad->[-1]} != $mobj->nargs ) {
$st->error( $f_l, _macro_args_error( $mobj, $pad ) );
return '';
}
if ( my $outer = $mobj->outer ) {
my @temp = @{$pad->[-1]};
@{$pad->[-1]}[ 0 .. $outer - 1 ] = @{$pad->[-2]}[ 0 .. $outer - 1 ];
@{$pad->[-1]}[ $outer .. $outer + $mobj->nargs ] = @temp;
}
Carp::croak('Macro call is too deep (> 100) on "foo"') if ++$depth > 100;
# print_raw_s
$output .= " Hello ";
# print
$sv = $pad->[ -1 ]->[ 0 ];
if ( ref($sv) eq TXt_RAW ) {
if(defined ${$sv}) {
$output .= $sv;
}
else {
$st->warn( ["foo", 13], "Use of nil to print" );
}
}
elsif ( defined $sv ) {
$sv =~ s/($html_metachars)/$html_escape{$1}/xmsgeo;
$output .= $sv;
}
else {
$st->warn( ["foo", 13], "Use of nil to print" );
}
# print_raw_s
$output .= "!\n";
$depth--;
pop( @$pad );
return mark_raw($output);
};
# process start
# print
$sv = $macro{ "foo" }->( $st, push_pad( $pad, [ $vars->{ "value" } ] ), [ "main", 5 ] );
if ( ref($sv) eq TXt_RAW ) {
if(defined ${$sv}) {
$output .= $sv;
}
else {
$st->warn( ["main", 6], "Use of nil to print" );
}
}
elsif ( defined $sv ) {
$sv =~ s/($html_metachars)/$html_escape{$1}/xmsgeo;
$output .= $sv;
}
else {
$st->warn( ["main", 6], "Use of nil to print" );
}
# process end
return $output;
}
So it makes the runtime speed much faster. Of course, its initial converting process costs time and memory.
SEE ALSO
AUTHOR
Makamaka Hannyaharamitu <makamaka at cpan.org>
LICENSE AND COPYRIGHT
Copyright (c) 2010 by Makamaka Hannyaharamitu (makamaka).
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.