HTML-Template-JIT
view release on metacpan or search on metacpan
JIT/Compiler.pm view on Meta::CPAN
package HTML::Template::JIT::Compiler;
use 5.006;
use strict;
use warnings;
our $VERSION = '0.01';
use HTML::Template;
use Carp qw(croak confess);
use File::Path qw(mkpath rmtree);
sub compile {
my %args = @_;
my $self = bless({});
# parse the template as usual
$self->{template} = HTML::Template->new(%args);
# setup state
$self->{jit_path} = $args{jit_path};
$self->{package} = $args{package};
$self->{package_dir} = $args{package_dir};
$self->{package_path} = $args{package_path};
$self->{jit_pool} = [];
$self->{jit_sym} = 0;
$self->{jit_debug} = $args{jit_debug};
$self->{text_size} = 0;
$self->{loop_context_vars} = $args{loop_context_vars};
$self->{max_depth} = 0;
$self->{global_vars} = $args{global_vars};
$self->{print_to_stdout} = $args{print_to_stdout};
$self->{case_sensitive} = $args{case_sensitive};
# compile internal representation into a chunk of C code
# get code for param function
my @code = $self->_output();
if ($self->{jit_debug}) {
print STDERR "###################### CODE START ######################\n\n";
open(INDENT, "| indent -kr > code.tmp");
print INDENT join("\n", @code);
close INDENT;
open(CODE, 'code.tmp');
print STDERR join('', <CODE>);
close(CODE);
unlink('code.tmp');
print STDERR "\n\n###################### CODE END ######################\n\n";
}
$self->_write_module(\@code);
# try to load the module and return package handle if successful
my $result;
eval { $result = require $self->{package_path}; };
return 1 if $result;
# don't leave failed compiles lying around unless we're debuging
rmtree($self->{package_dir}, 0, 0) unless $self->{jit_debug};
die $@ if $@;
return 0;
}
# writes out the module file
sub _write_module {
my ($self, $code) = @_;
# make directory
mkpath($self->{package_dir}, 0, 0700);
# open module file
open(MODULE, ">$self->{package_path}") or die "Unable to open $self->{package_path} for output : $!";
my $inline_debug = "";
my $optimize = "-O3";
if ($self->{jit_debug}) {
$inline_debug = ", CLEAN_AFTER_BUILD => 0";
$optimize = "-g";
}
# print out preamble
print MODULE <<END;
package $self->{package};
use base 'HTML::Template::JIT::Base';
use Inline C => Config => OPTIMIZE => "$optimize", DIRECTORY => "$self->{package_dir}" $inline_debug;
use Inline C => <<'CODE_END';
END
# print out code
print MODULE join("\n", @$code), "\nCODE_END\n";
# output the param hash
print MODULE "our \%param_hash = (\n", join(',', $self->_param_hash([])), ");\n";
# empty param map
print MODULE "our \%param_map;\n";
# note case sensitivity
print MODULE "our \$case_sensitive = $self->{case_sensitive};\n";
print MODULE "\n1;\n";
# all done
close MODULE;
}
# construct the output function
sub _output {
my $self = shift;
my $template = $self->{template};
# construct body of output
my @code = $self->_output_template($template, 0);
( run in 0.613 second using v1.01-cache-2.11-cpan-39bf76dae61 )