made a huge optimization for loops (up to 50% faster now)

git-svn-id: http://svn.twig-project.org/trunk@117 93ef8e89-cb99-4229-a87c-7fa0fa45744b
This commit is contained in:
fabien
2009-11-07 19:48:10 +00:00
parent 1bb24438b5
commit 9cfb40b0fa
2 changed files with 19 additions and 71 deletions
+6 -3
View File
@@ -58,10 +58,13 @@ class Twig_Node_For extends Twig_Node implements Twig_NodeListInterface
$compiler->write("\$context['_iterated'] = false;\n");
}
$var = rand(1, 999999);
$compiler
->write('foreach (twig_iterate($context, ')
->write("\$seq$var = twig_iterator_to_array(")
->subcompile($this->seq)
->raw(") as \$iterator)\n")
->raw(");\n")
->write("\$context['loop']['length'] = count(\$seq$var);\n")
->write("for (\$i$var = 0; \$i$var < \$context['loop']['length']; \$i$var++)\n")
->write("{\n")
->indent()
;
@@ -71,7 +74,7 @@ class Twig_Node_For extends Twig_Node implements Twig_NodeListInterface
$compiler->write("\$context['_iterated'] = true;\n");
}
$compiler->write('twig_set_loop_context($context, $iterator, ');
$compiler->write("twig_set_loop_context(\$context, \$seq$var, \$i$var, ");
if ($this->isMultitarget)
{
+13 -68
View File
@@ -4,103 +4,48 @@
* This file is part of Twig.
*
* (c) 2009 Fabien Potencier
* (c) 2009 Armin Ronacher
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Twig_LoopContextIterator implements Iterator
function twig_iterator_to_array($seq)
{
public $context;
public $seq;
public $idx;
public $length;
public $parent;
public function __construct(&$context, $seq, $parent)
{
$this->context = $context;
$this->seq = $seq;
$this->length = count($this->seq);
$this->parent = $parent;
}
public function rewind()
{
$this->idx = 0;
}
public function key()
{
}
public function valid()
{
return $this->idx < $this->length;
}
public function next()
{
$this->idx++;
}
public function current()
{
return $this;
}
}
function twig_iterate(&$context, $seq)
{
$parent = isset($context['loop']) ? $context['loop'] : null;
// convert the sequence to an array of values
// we convert Iterators as an array
// as our iterator access the sequence as an array
if (is_array($seq))
{
$array = array_values($seq);
return array_values($seq);
}
elseif (is_object($seq) && $seq instanceof Iterator)
{
$array = iterator_to_array($seq, false);
return iterator_to_array($seq, false);
}
else
{
$array = array();
return array();
}
$context['loop'] = array('parent' => $parent);
return new Twig_LoopContextIterator($context, $array, $parent);
}
function twig_set_loop_context(&$context, $iterator, $target)
function twig_set_loop_context(&$context, $seq, $idx, $target)
{
$idx = $iterator->idx;
if (is_array($target))
{
foreach ($target as $key => $value)
{
$context[$value] = $iterator->seq[$idx][$key];
}
$context[$target[0]] = $seq[$idx][0];
$context[$target[1]] = $seq[$idx][1];
}
else
{
$context[$target] = $iterator->seq[$idx];
$context[$target] = $seq[$idx];
}
$context['loop'] = array(
'parent' => $iterator->parent,
'length' => $iterator->length,
'parent' => $context['_parent'],
'length' => $context['loop']['length'],
'index0' => $idx,
'index' => $idx + 1,
'revindex0' => $iterator->length - $idx - 1,
'revindex' => $iterator->length - $idx,
'revindex0' => $context['loop']['length'] - $idx - 1,
'revindex' => $context['loop']['length'] - $idx,
'first' => $idx == 0,
'last' => $idx + 1 == $iterator->length,
'last' => $idx + 1 == $context['loop']['length'],
);
}