remove dead code from VMX::Template + debug VMX::Template new parser

databind
vitalif 2009-12-24 10:35:50 +00:00 committed by Vitaliy Filippov
parent 61a191e15d
commit ab5e431069
1 changed files with 33 additions and 217 deletions

View File

@ -13,7 +13,6 @@ use POSIX;
my $mtimes = {}; # время изменения файлов
my $uncompiled_code = {}; # нескомпилированный код
my $compiled_code = {}; # скомпилированный код (sub'ы)
my $assigncache = {}; # кэш eval'ов присвоений
# Конструктор
# $obj = new VMX::Template, %params
@ -41,32 +40,6 @@ sub new
bless $self, $class;
}
# Функция задаёт имена файлов для хэндлов
# $obj->set_filenames (handle1 => 'template1.tpl', ...)
sub set_filenames
{
my $self = shift;
my %fns = @_;
while (my ($k, $v) = each %fns)
{
$self->{filenames}->{$k} = "$v";
}
return 1;
}
# Задать код для хэндлов
# $obj->set_code (handle1 => "{CODE} - Template code", ...);
sub set_code
{
my $self = shift;
my %codes = @_;
while (my ($k, $v) = each %codes)
{
$self->{filenames}->{$k} = \ $v;
}
return 1;
}
# Функция уничтожает данные шаблона
# $obj->clear()
sub clear
@ -75,67 +48,52 @@ sub clear
return 1;
}
# Функция очищает кэш в памяти
sub clear_memory_cache
{
my $self = shift;
%$compiled_code = ();
%$uncompiled_code = ();
%$mtimes = ();
return $self;
}
# Получить хеш для записи данных
sub vars
{
my $self = shift;
my ($vars) = @_;
my $t = $self->{tpldata};
$self->{tpldata} = $vars if $vars;
return $self->{tpldata};
}
# Функция выполняет код шаблона, не выводя страницу
# Нужно, чтобы выполнить все присваивания переменных.
# $obj->preparse('handle')
sub preparse
{
my $self = shift;
my ($handle) = @_;
my $fn = $self->{filenames}->{$handle};
my $textref;
unless (ref $fn)
{
die "[Template] unknown handle '$handle'"
unless $fn;
$fn = $self->{root}.$fn
if $fn !~ m!^/!so;
die "[Template] couldn't load template file '$fn' for handle '$handle'"
unless $textref = $self->loadfile($fn);
}
else
{
$textref = $fn;
$fn = undef;
}
return $self;
return $t;
}
# Функция загружает, компилирует и возвращает результат для хэндла
# $page = $obj->parse('handle')
# $page = $obj->parse( 'file/name.tpl' );
# Если имя файла - ссылка на скаляр, значит, это ссылка на код шаблона
# $page = $obj->parse( \ 'inlined template {CODE}' );
sub parse
{
my $self = shift;
my ($handle) = @_;
my $fn = $self->{filenames}->{$handle};
my ($fn) = @_;
my $textref;
unless (ref $fn)
{
die "[Template] unknown handle '$handle'"
unless $fn;
$fn = $self->{root}.$fn
if $fn !~ m!^/!so;
die "[Template] couldn't load template file '$fn' for handle '$handle'"
die __PACKAGE__.": empty filename '$fn'" unless length $fn;
$fn = $self->{root}.$fn if $fn !~ m!^/!so;
die __PACKAGE__.": couldn't load template file '$fn'"
unless $textref = $self->loadfile($fn);
}
else
{
return $$fn unless $$fn;
$textref = $fn;
$fn = undef;
}
my $sub = $self->compile($textref, $handle, $fn);
my $sub = $self->compile($textref, $fn);
my $str = eval { &$sub($self) };
die "[Template] error running '$handle': $@" if $@;
&{$self->{wrapper}} ($str) if $self->{wrapper};
die __PACKAGE__.": error running '$fn': $@" if $@;
&{$self->{wrapper}}($str) if $self->{wrapper};
return $str;
}
@ -175,134 +133,13 @@ sub loadfile
return $uncompiled_code->{$fn};
}
# Функция присваивает переменные блока в новую итерацию
# $obj->assign_block_vars ($block, varname1 => value1, varname2 => value2, ...)
# Так тоже можно (при этом избежим лишнего копирования хеша!):
# $obj->assign_block_vars ($block, { varname1 => value1, varname2 => value2, ... })
sub assign_block_vars
{
my $self = shift;
my $block = shift;
my $vararray;
if (@_ > 1)
{
# копирование хеша, да...
$vararray = { @_ };
}
else
{
# а так можно и не копировать
($vararray) = @_;
}
$block =~ s/^\.+//so;
$block =~ s/\.+$//so;
if (!$block)
{
# если не блок, а корневой уровень
$self->assign_vars($vararray);
}
elsif ($block !~ /\.[^\.]/so)
{
# если блок, но не вложенный
$block =~ s/\.*$/./so; # добавляем . в конец, если надо
$self->{tpldata}->{$block} ||= [];
push @{$self->{tpldata}->{$block}}, $vararray;
}
else
{
# если вложенный блок
my $ev;
$block =~ s/\.+$//so; # обрезаем точки в конце (хоть их 10 там)
unless ($ev = $assigncache->{"=$block"})
{
$ev = '$_[0]';
my @blocks = split /\./, $block;
my $lastblock = pop @blocks;
foreach (@blocks)
{
$ev .= "{'$_'}";
$ev .= "[\$\#\{$ev\}]";
}
$ev .= "{'$lastblock'}";
$ev = "return sub { $ev ||= []; push \@\{$ev\}, \$_[1]; }";
$ev = $assigncache->{"=$block"} = eval $ev;
}
&$ev($self->{tpldata}, $vararray);
}
return 1;
}
# Функция добавляет переменные к текущей итерации блока
# $obj->append_block_vars ($block, varname1 => value1, varname2 => value2, ...)
sub append_block_vars
{
my $self = shift;
my $block = shift;
my %vararray = @_;
my $lastit;
if (!$block || $block eq '.')
{
# если не блок, а корневой уровень
$self->assign_vars(@_);
}
elsif ($block !~ /\../so)
{
# если блок, но не вложенный
$block =~ s/\.*$/./so; # добавляем . в конец, если надо
$self->{tpldata}{$block} ||= [];
$lastit = $#{$self->{tpldata}{$block}};
$lastit = 0 if $lastit < 0;
$self->{tpldata}{$block}[$lastit]{$_} = $vararray{$_}
for keys %vararray;
}
else
{
# если вложенный блок
my $ev;
$block =~ s/\.+$//so; # обрезаем точки в конце (хоть их 10 там)
unless ($ev = $assigncache->{"+$block"})
{
$ev = '$_[0]';
my @blocks = split /\.+/, $block;
foreach (@blocks)
{
$ev .= "{'$_'}";
$ev .= "[\$#\{$ev\}]";
}
$ev = 'return sub { for my $k (keys %{$_[1]}) { '.$ev.'{$k} = $_[1]->{$k}; } }';
$ev = $assigncache->{"+$block"} = eval $ev;
}
&$ev($self->{tpldata}, \%vararray);
}
return 1;
}
# Функция присваивает переменные корневого уровня
# $obj->assign_vars (varname1 => value1, varname2 => value2, ...)
sub assign_vars
{
my $self = shift;
my $h;
if (@_ > 1 || !ref $_[0])
{
$h = { @_ };
}
else
{
$h = $_[0];
}
$self->{tpldata} ||= {};
$self->{tpldata}->{$_} = $h->{$_} for keys %$h;
return 1;
}
# Функция компилирует код.
# $sub = $self->compile(\$code, $handle, $fn);
# $sub = $self->compile(\$code, $fn);
# print &$sub($self);
sub compile
{
my $self = shift;
my ($coderef, $handle, $fn) = @_;
my ($coderef, $fn) = @_;
return $compiled_code->{$coderef} if $compiled_code->{$coderef};
# кэширование на диске
@ -315,7 +152,7 @@ sub compile
$compiled_code->{$coderef} = do $h;
if ($@)
{
warn "[Template] error compiling '$handle': [$@] in FILE: $h";
warn __PACKAGE__.": error compiling '$fn': [$@] in FILE: $h";
unlink $h;
}
else
@ -325,21 +162,6 @@ sub compile
}
}
# прописываем путь к текущему шаблону в переменную
$self->{cur_template_path} = $self->{cur_template} = '';
if ($fn)
{
$self->{cur_template} = $fn;
$self->{cur_template} = substr $self->{cur_template}, length $self->{root}
if substr($self->{cur_template}, 0, length $self->{root}) eq $self->{root};
$self->{cur_template} =~ s/\.[^\.]+$//iso;
$self->{cur_template} =~ s/:+//gso;
$self->{cur_template} =~ s!/+!:!gso;
$self->{cur_template} =~ s/[^\w_:]+//gso;
$self->{cur_template_path} = '->{"' . join('"}->{"',
map { lc } split /:/, $self->{cur_template}) . '"}';
}
my $code = $$coderef;
Encode::_utf8_on($code) if $self->{use_utf8};
@ -375,7 +197,7 @@ sub compile
for $i (0..$#p)
{
# ближайшее найденное
$b = $i if !$b || $p[$i] >= 0 && $p[$i] < $p[$b];
$b = $i if $p[$i] >= 0 && (!$b || $p[$i] < $p[$b]);
}
if (defined $b)
{
@ -386,7 +208,7 @@ sub compile
$e = index $code, $blk[$b][1], $pp;
if ($e >= 0)
{
$frag = substr $code, $p[$b]+$blk[$b][3], $e-$p[$b]-$blk[$b][3]-$blk[$b][4];
$frag = substr $code, $p[$b]+$blk[$b][3], $e-$p[$b]-$blk[$b][3];
$f = $blk[$b][2];
$frag = $self->$f($frag);
if (defined $frag)
@ -401,7 +223,7 @@ sub compile
$pp = 0;
}
$r .= $frag;
substr $code, 0, $e-$p[$b], '';
substr $code, 0, $e+$blk[$b][4]-$p[$b], '';
}
}
}
@ -419,7 +241,6 @@ sub compile
'sub {
my $self = shift;
my $t = "";
my $_current_template = [ split /:/, \'' . $self->{cur_template} . '\' ];
' . $r . '
return $t;
}';
@ -437,13 +258,13 @@ return $t;
}
else
{
warn "[Template] error caching '$handle': $! while opening $h";
warn __PACKAGE__.": error caching '$fn': $! while opening $h";
}
}
# компилируем код
$compiled_code->{$coderef} = eval $code;
die "[Template] error compiling '$handle': [$@] in CODE:\n$code" if $@;
die __PACKAGE__.": error compiling '$fn': [$@] in CODE:\n$code" if $@;
# возвращаем ссылку на процедуру
return $compiled_code->{$coderef};
@ -486,7 +307,7 @@ sub compile_code_fragment
{
return "} else {";
}
elsif ($e =~ /^(BEGIN|FOR(EACH)?)\s+([a-z_][a-z0-9_]*)(?:\s+AT\s+(.+))?(?:\s+BY\s+(.+))?(?:\s+TO\s+(.+))?$/iso)
elsif ($e =~ /^(?:BEGIN|FOR(?:EACH)?)\s+([a-z_][a-z0-9_]*)(?:\s+AT\s+(.+))?(?:\s+BY\s+(.+))?(?:\s+TO\s+(.+))?$/iso)
{
my $ref = $self->varref([@{$self->{blocks}}, $1]);
my $at = 0;
@ -569,12 +390,7 @@ EOF
{
my $n = $1;
$n =~ s/\'|\\/\\$&/gso;
$t = "\$t .= \$self->parse('_INCLUDE$n');\n";
unless ($self->{included}->{$n})
{
$t = "\$self->set_filenames('_INCLUDE$n' => '$n');\n$t";
$self->{included}->{$n} = 1;
}
$t = "\$t .= \$self->parse('$n');\n";
return $t;
}
else