> -----Original Message----- > From: [EMAIL PROTECTED] > [mailto:[EMAIL PROTECTED] On > Behalf Of Sam Tregar > Sent: Monday, July 11, 2005 8:00 PM > To: Emanuele Zeppieri > Cc: html-template-users@lists.sourceforge.net > Subject: Re: [htmltmpl] (no subject) > > > On Mon, 11 Jul 2005, Emanuele Zeppieri wrote: > > > Well, I'm probably missing something (or everything), but > it seems to me > > that the following compiled code layout could solve the problem: > > > > JUMP to A IF false > > ... # first true instruction > > ... > > ... # last true instruction > > JUMP TO B > > A: ... # first false instruction > > ... > > ... # last false instruction > > B: ... # normal execution after the IF/ELSE, if any... > > Yup, that would do it. That's much easier than trying to store state > from the first one. So, when can I see a patch?
Here it is Sam. It guarantees that any conditional predicate is never re-evaluated and, as an extra bonus, it also speeds up the output() execution in presence of a TMPL_ELSE tag. It passed all the tests under both Linux and Windows and I've also added a new test for HTML::Template::Expr (05random.t) which reproduces the case showed by Jochen Cichon. The patch is against Template.pm ver. 2.7. The patch is attached to this message (as well as the new test) and also listed below. Feel free to remove my name from the comments (left there merely to easily find the relevant lines, just in case a correction is needed or a further refinement comes to my mind). Cheers, Emanuele. --- Template.pm.original Sat Jun 26 08:57:09 2004 +++ Template.pm Wed Jul 13 03:35:03 2005 @@ -897,7 +897,7 @@ # accesses into "objects". I used to use 'use constant' but that # seems to cause occasional irritating warnings in older Perls. package HTML::Template::LOOP; -sub TEMPLATE_HASH () { 0; } +sub TEMPLATE_HASH () { 0 }; sub PARAM_SET () { 1 }; package HTML::Template::COND; @@ -908,6 +908,7 @@ sub JUMP_IF_TRUE () { 2 }; sub JUMP_ADDRESS () { 3 }; sub WHICH () { 4 }; +sub UNCONDITIONAL_JUMP () { 5 }; sub WHICH_IF () { 0 }; sub WHICH_UNLESS () { 1 }; @@ -2183,7 +2184,15 @@ my $else = HTML::Template::COND->new($cond->[HTML::Template::COND::VARIABLE]); $else->[HTML::Template::COND::WHICH] = $cond->[HTML::Template::COND::WHICH]; - $else->[HTML::Template::COND::JUMP_IF_TRUE] = not $cond->[HTML::Template::COND::JUMP_IF_TRUE]; + + # <Emanuele Zeppieri> + # Removed because now unnecessary, as we'll unconditionally jump over + #$else->[HTML::Template::COND::JUMP_IF_TRUE] = not $cond->[HTML::Template::COND::JUMP_IF_TRUE]; + + # This is to mark this COND opcode as generated by a TMPL_ELSE tag, + # so that we can just jump over during the output() execution. + $else->[HTML::Template::COND::UNCONDITIONAL_JUMP] = 1; + # </Emanuele Zeppieri> # need end-block resolution? if (defined($cond->[HTML::Template::COND::VARIABLE_TYPE])) { @@ -2201,7 +2210,7 @@ # the IF fails and falls though, output will reach the else # and jump to the /if address. $cond->[HTML::Template::COND::JUMP_ADDRESS] = $#pstack; - + } elsif ($which eq 'TMPL_INCLUDE') { # handle TMPL_INCLUDEs $options->{debug} and print STDERR "### HTML::Template Debug ### $fname : line $fcounter : INCLUDE $name \n"; @@ -2657,7 +2666,12 @@ croak("HTML::Template->output() : fatal error in loop output : $@") if $@; } - } elsif ($type eq 'HTML::Template::COND') { + } elsif ($type eq 'HTML::Template::COND') { + + if ($line->[HTML::Template::COND::UNCONDITIONAL_JUMP]) { + $x = $line->[HTML::Template::COND::JUMP_ADDRESS] + } else { + if ($line->[HTML::Template::COND::JUMP_IF_TRUE]) { if ($line->[HTML::Template::COND::VARIABLE_TYPE] == HTML::Template::COND::VARIABLE_TYPE_VAR) { if (defined ${$line->[HTML::Template::COND::VARIABLE]}) { @@ -2689,6 +2703,9 @@ not scalar @{$line->[HTML::Template::COND::VARIABLE][HTML::Template::LOOP::PARAM_SE T]}); } } + + } + } elsif ($type eq 'HTML::Template::NOOP') { next; } elsif ($type eq 'HTML::Template::DEFAULT') {
Template.pm.patch
Description: Binary data
05random.t
Description: Binary data