made a huge optimization for loops (up to 50% faster now)
authorfabien <fabien@93ef8e89-cb99-4229-a87c-7fa0fa45744b>
Sat, 7 Nov 2009 19:48:10 +0000 (19:48 +0000)
committerfabien <fabien@93ef8e89-cb99-4229-a87c-7fa0fa45744b>
Sat, 7 Nov 2009 19:48:10 +0000 (19:48 +0000)
git-svn-id: http://svn.twig-project.org/trunk@117 93ef8e89-cb99-4229-a87c-7fa0fa45744b

lib/Twig/Node/For.php
lib/Twig/runtime_for.php

index e6d8482..184e470 100644 (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)
     {
index c587873..c526153 100644 (file)
  * 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'],
   );
 }