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

Text::Xslate

Text::Xslate::PP

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.