added compiled template support
Uri Guttman [Wed, 24 Dec 2008 06:36:30 +0000 (01:36 -0500)]
lib/Template/Simple.pm

index 4dd68a4..165f132 100644 (file)
@@ -4,10 +4,10 @@ use warnings;
 use strict;
 
 use Carp ;
+use Data::Dumper ;
 use Scalar::Util qw( reftype ) ;
 use File::Slurp ;
 
-use Data::Dumper ;
 
 our $VERSION = '0.03';
 
@@ -109,14 +109,14 @@ sub compile {
        my $code_body = $self->_compile_chunk( '', "${$tmpl_ref}", "\t" ) ;
 
        my $source = <<CODE ;
-
 no warnings ;
 
 sub {
        my( \$data ) = \@_ ;
 
-       my \$out = $code_body ;
+       my \$out ;
 
+$code_body
        return \\\$out ;
 }
 CODE
@@ -131,30 +131,38 @@ print $@ if $@ ;
        $self->{source_cache}{$template_name} = $source ;
 }
 
-sub get_source {
+sub _compile_chunk {
 
-       my( $self, $template_name ) = @_ ;
+       my( $self, $chunk_name, $template, $indent ) = @_ ;
 
-       return $self->{source_cache}{$template_name} ;
-}
+       return '' unless length $template ;
 
+# generate a lookup in data for this chunk name (unless it is the top
+# level). this descends down the data tree during rendering
 
-sub _compile_chunk {
+       my $data_init = $chunk_name ? "\$data->{$chunk_name}" : '$data' ;
 
-       my( $self, $chunk_name, $template, $indent ) = @_ ;
+       my $code = <<CODE ;
+${indent}my \@data = $data_init ;
+${indent}while( defined( my \$data = shift \@data ) ) {
 
-       return '' unless length $template ;
+${indent}      if ( ref \$data eq 'ARRAY' ) {
+${indent}              push \@data, \@{\$data} ;
+${indent}              next ;
+${indent}      }
 
-       my @parts ;
+CODE
+
+       $indent .= "\t" ;
 
 # loop all nested chunks and the text separating them
 
        while( $template =~ m{$self->{chunk_re}} ) {
 
-# grab the pre-match text and compile its scalars and save all of its parts
+# get the pre-match text and compile its scalars and text. append to the code
 
-               push @parts, $self->_compile_scalars(
-                               substr( $template, 0, $-[0] ) ) ;
+               $code .= $self->_compile_scalars(
+                       substr( $template, 0, $-[0] ), $indent ) ;
 
 # print "OFF: $-[0] $+[0]\n" ;
 # print "PRE: [", substr( $template, 0, $-[0] ), "]\n\n" ;
@@ -162,95 +170,43 @@ sub _compile_chunk {
 # print "TRUNC: [", substr( $template, 0, $+[0] ), "]\n\n" ;
 # print "LEFT: [$template]\n\n" ;
 
-# compile the nested chunk and save its parts
+# compile the nested chunk and append to the code
 
-               push @parts, $self->_compile_chunk( $1, $2, "$indent\t\t" ) ;
+               $code .= $self->_compile_chunk( $1, $2, $indent ) ;
 
 # chop off the pre-match and the chunk
 
                substr( $template, 0, $+[0], '' ) ;
-
-# print "LEFT2: [$template]\n\n" ;
-# print Dumper \@parts ;
-
        }
 
-# compile trailing text for scalars and save all of its parts
-
-       push @parts, $self->_compile_scalars( $template ) ;
+# compile trailing text for scalars and append to the code
 
-# generate the code for this chunk
-
-# start it with a do{} block open
-
-       my $code = <<CODE ;
-do {
-CODE
-
-       $indent .= "\t" ;
-
-# generate a lookup in data for this chunk name (unless it is the top
-# level). this descends down the data tree during rendering
-
-       $code .= <<CODE if $chunk_name ;
-${indent}my \$data = \$data->{$chunk_name} ;
-CODE
-
-# add the loop code to handle a scalar or an array
-
-       $code .= <<CODE ;
-${indent}my \$out ;
-
-${indent}my \@data = \$data ;
-${indent}while( defined( my \$data = shift \@data ) ) {
-
-${indent}      if ( ref \$data eq 'ARRAY' ) {
-${indent}              push \@data, \@{\$data} ;
-${indent}              next ;
-${indent}      }
-
-       ${indent}\$out .= ref \$data ne 'HASH' ? \$data :
-CODE
-
-#${indent}foreach my \$data ( ref \$data eq 'ARRAY' ? \@{\$data} : \$data ) {
-
-
-
-       $indent .= "\t" ;
-
-# now generate the code to output all the parts of this chunk. they
-# are all concatentated by the . operator
-
-       $code .= $indent . join( "\n$indent.\n$indent", @parts ) ;
+       $code .= $self->_compile_scalars( $template, $indent ) ;
 
        chop $indent ;
 
-# now we end the .= statement, the loop and the do block for this chunk
+# now we end the loop for this chunk
        $code .= <<CODE ;
- ;
 $indent}
-$indent\$out ;
 CODE
 
-       chop $indent ;
-       $code .= "$indent}" ;
-
        return $code ;
 }
 
 sub _compile_scalars {
 
-       my( $self, $template ) = @_ ;
+       my( $self, $template, $indent ) = @_ ;
 
 # if the template is empty return no parts
 
-       return unless length $template ;
+       return '' unless length $template ;
 
        my @parts ;
 
        while( $template =~ m{$self->{scalar_re}}g ) {
 
-# keep the text before the scalar markup and the code to access the scalar
+# get the pre-match text before the scalar markup and generate code to
+# access the scalar
 
                push( @parts,
                        dump_text( substr( $template, 0, $-[0] ) ),
@@ -266,10 +222,16 @@ sub _compile_scalars {
 
        push @parts, dump_text( $template ) ;
 
-       return @parts ;
+       my $parts_code = join( "\n$indent.\n$indent", @parts ) ;
+
+       return <<CODE ;
+
+${indent}\$out .= ref \$data ne 'HASH' ? \$data :
+${indent}$parts_code ;
+
+CODE
 }
 
-use Data::Dumper ;
 
 sub dump_text {
 
@@ -287,6 +249,13 @@ sub dump_text {
        return $dumped ;
 }
 
+sub get_source {
+
+       my( $self, $template_name ) = @_ ;
+
+       return $self->{source_cache}{$template_name} ;
+}
+
 sub render {
 
        my( $self, $template_name, $data ) = @_ ;