Index: inc/libs/twig/CHANGELOG
===================================================================
--- inc/libs/twig/CHANGELOG	(revision 991)
+++ inc/libs/twig/CHANGELOG	(revision 1101)
@@ -1,2 +1,30 @@
+* 1.12.2 (2013-02-09)
+
+ * fixed the timezone used by the date filter and function when the given date contains a timezone (like 2010-01-28T15:00:00+02:00)
+ * fixed globals when getGlobals is called early on
+ * added the first and last filter
+
+* 1.12.1 (2013-01-15)
+
+ * added support for object instances as the second argument of the constant function
+ * relaxed globals management to avoid a BC break
+ * added support for {{ some_string[:2] }}
+
+* 1.12.0 (2013-01-08)
+
+ * added verbatim as an alias for the raw tag to avoid confusion with the raw filter
+ * fixed registration of tests and functions as anonymous functions
+ * fixed globals management
+
+* 1.12.0-RC1 (2012-12-29)
+
+ * added an include function (does the same as the include tag but in a more flexible way)
+ * added the ability to use any PHP callable to define filters, functions, and tests
+ * added a syntax error when using a loop variable that is not defined
+ * added the ability to set default values for macro arguments
+ * added support for named arguments for filters, tests, and functions
+ * moved filters/functions/tests syntax errors to the parser
+ * added support for extended ternary operator syntaxes
+
 * 1.11.1 (2012-11-11)
 
Index: inc/libs/twig/Compiler.php
===================================================================
--- inc/libs/twig/Compiler.php	(revision 991)
+++ inc/libs/twig/Compiler.php	(revision 1101)
@@ -257,5 +257,5 @@
     public function outdent($step = 1)
     {
-        // can't outdent by more steps that the current indentation level
+        // can't outdent by more steps than the current indentation level
         if ($this->indentation < $step) {
             throw new LogicException('Unable to call outdent() as the indentation would become negative');
Index: inc/libs/twig/CompilerInterface.php
===================================================================
--- inc/libs/twig/CompilerInterface.php	(revision 991)
+++ inc/libs/twig/CompilerInterface.php	(revision 1101)
@@ -15,4 +15,5 @@
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 interface Twig_CompilerInterface
Index: inc/libs/twig/Environment.php
===================================================================
--- inc/libs/twig/Environment.php	(revision 991)
+++ inc/libs/twig/Environment.php	(revision 1101)
@@ -18,5 +18,5 @@
 class Twig_Environment
 {
-    const VERSION = '1.11.1';
+    const VERSION = '1.12.2';
 
     protected $charset;
@@ -37,4 +37,5 @@
     protected $globals;
     protected $runtimeInitialized;
+    protected $extensionInitialized;
     protected $loadedTemplates;
     protected $strictVariables;
@@ -103,9 +104,4 @@
         $this->baseTemplateClass  = $options['base_template_class'];
         $this->autoReload         = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
-        $this->extensions         = array(
-            'core'      => new Twig_Extension_Core(),
-            'escaper'   => new Twig_Extension_Escaper($options['autoescape']),
-            'optimizer' => new Twig_Extension_Optimizer($options['optimizations']),
-        );
         $this->strictVariables    = (bool) $options['strict_variables'];
         $this->runtimeInitialized = false;
@@ -113,12 +109,10 @@
         $this->functionCallbacks = array();
         $this->filterCallbacks = array();
-        $this->staging = array(
-            'functions'     => array(),
-            'filters'       => array(),
-            'tests'         => array(),
-            'token_parsers' => array(),
-            'visitors'      => array(),
-            'globals'       => array(),
-        );
+
+        $this->addExtension(new Twig_Extension_Core());
+        $this->addExtension(new Twig_Extension_Escaper($options['autoescape']));
+        $this->addExtension(new Twig_Extension_Optimizer($options['optimizations']));
+        $this->extensionInitialized = false;
+        $this->staging = new Twig_Extension_Staging();
     }
 
@@ -270,5 +264,5 @@
     public function getTemplateClass($name, $index = null)
     {
-        return $this->templateClassPrefix.md5($this->loader->getCacheKey($name)).(null === $index ? '' : '_'.$index);
+        return $this->templateClassPrefix.md5($this->getLoader()->getCacheKey($name)).(null === $index ? '' : '_'.$index);
     }
 
@@ -325,8 +319,8 @@
         if (!class_exists($cls, false)) {
             if (false === $cache = $this->getCacheFilename($name)) {
-                eval('?>'.$this->compileSource($this->loader->getSource($name), $name));
+                eval('?>'.$this->compileSource($this->getLoader()->getSource($name), $name));
             } else {
                 if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) {
-                    $this->writeCacheFile($cache, $this->compileSource($this->loader->getSource($name), $name));
+                    $this->writeCacheFile($cache, $this->compileSource($this->getLoader()->getSource($name), $name));
                 }
 
@@ -363,5 +357,5 @@
         }
 
-        return $this->loader->isFresh($name, $time);
+        return $this->getLoader()->isFresh($name, $time);
     }
 
@@ -560,4 +554,8 @@
     public function getLoader()
     {
+        if (null === $this->loader) {
+            throw new LogicException('You must set a loader first.');
+        }
+
         return $this->loader;
     }
@@ -630,11 +628,9 @@
     public function addExtension(Twig_ExtensionInterface $extension)
     {
+        if ($this->extensionInitialized) {
+            throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName()));
+        }
+
         $this->extensions[$extension->getName()] = $extension;
-        $this->parsers = null;
-        $this->visitors = null;
-        $this->filters = null;
-        $this->tests = null;
-        $this->functions = null;
-        $this->globals = null;
     }
 
@@ -642,15 +638,17 @@
      * Removes an extension by name.
      *
+     * This method is deprecated and you should not use it.
+     *
      * @param string $name The extension name
+     *
+     * @deprecated since 1.12 (to be removed in 2.0)
      */
     public function removeExtension($name)
     {
+        if ($this->extensionInitialized) {
+            throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name));
+        }
+
         unset($this->extensions[$name]);
-        $this->parsers = null;
-        $this->visitors = null;
-        $this->filters = null;
-        $this->tests = null;
-        $this->functions = null;
-        $this->globals = null;
     }
 
@@ -684,6 +682,9 @@
     public function addTokenParser(Twig_TokenParserInterface $parser)
     {
-        $this->staging['token_parsers'][] = $parser;
-        $this->parsers = null;
+        if ($this->extensionInitialized) {
+            throw new LogicException('Unable to add a token parser as extensions have already been initialized.');
+        }
+
+        $this->staging->addTokenParser($parser);
     }
 
@@ -695,25 +696,6 @@
     public function getTokenParsers()
     {
-        if (null === $this->parsers) {
-            $this->parsers = new Twig_TokenParserBroker();
-
-            if (isset($this->staging['token_parsers'])) {
-                foreach ($this->staging['token_parsers'] as $parser) {
-                    $this->parsers->addTokenParser($parser);
-                }
-            }
-
-            foreach ($this->getExtensions() as $extension) {
-                $parsers = $extension->getTokenParsers();
-                foreach ($parsers as $parser) {
-                    if ($parser instanceof Twig_TokenParserInterface) {
-                        $this->parsers->addTokenParser($parser);
-                    } elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
-                        $this->parsers->addTokenParserBroker($parser);
-                    } else {
-                        throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances');
-                    }
-                }
-            }
+        if (!$this->extensionInitialized) {
+            $this->initExtensions();
         }
 
@@ -747,6 +729,9 @@
     public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
     {
-        $this->staging['visitors'][] = $visitor;
-        $this->visitors = null;
+        if ($this->extensionInitialized) {
+            throw new LogicException('Unable to add a node visitor as extensions have already been initialized.', $extension->getName());
+        }
+
+        $this->staging->addNodeVisitor($visitor);
     }
 
@@ -758,12 +743,6 @@
     public function getNodeVisitors()
     {
-        if (null === $this->visitors) {
-            foreach ($this->getExtensions() as $extension) {
-                foreach ($extension->getNodeVisitors() as $visitor) {
-                    $this->addNodeVisitor($visitor);
-                }
-            }
-
-            $this->visitors = $this->staging['visitors'];
+        if (!$this->extensionInitialized) {
+            $this->initExtensions();
         }
 
@@ -774,11 +753,23 @@
      * Registers a Filter.
      *
-     * @param string               $name   The filter name
-     * @param Twig_FilterInterface $filter A Twig_FilterInterface instance
-     */
-    public function addFilter($name, Twig_FilterInterface $filter)
-    {
-        $this->staging['filters'][$name] = $filter;
-        $this->filters = null;
+     * @param string|Twig_SimpleFilter               $name   The filter name or a Twig_SimpleFilter instance
+     * @param Twig_FilterInterface|Twig_SimpleFilter $filter A Twig_FilterInterface instance or a Twig_SimpleFilter instance
+     */
+    public function addFilter($name, $filter = null)
+    {
+        if ($this->extensionInitialized) {
+            throw new LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name));
+        }
+
+        if (!$name instanceof Twig_SimpleFilter && !($filter instanceof Twig_SimpleFilter || $filter instanceof Twig_FilterInterface)) {
+            throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter');
+        }
+
+        if ($name instanceof Twig_SimpleFilter) {
+            $filter = $name;
+            $name = $filter->getName();
+        }
+
+        $this->staging->addFilter($name, $filter);
     }
 
@@ -791,10 +782,10 @@
      * @param string $name The filter name
      *
-     * @return Twig_Filter|false A Twig_Filter instance or false if the filter does not exists
+     * @return Twig_Filter|false A Twig_Filter instance or false if the filter does not exist
      */
     public function getFilter($name)
     {
-        if (null === $this->filters) {
-            $this->getFilters();
+        if (!$this->extensionInitialized) {
+            $this->initExtensions();
         }
 
@@ -841,12 +832,6 @@
     public function getFilters()
     {
-        if (null === $this->filters) {
-            foreach ($this->getExtensions() as $extension) {
-                foreach ($extension->getFilters() as $name => $filter) {
-                    $this->addFilter($name, $filter);
-                }
-            }
-
-            $this->filters = $this->staging['filters'];
+        if (!$this->extensionInitialized) {
+            $this->initExtensions();
         }
 
@@ -857,11 +842,23 @@
      * Registers a Test.
      *
-     * @param string             $name The test name
-     * @param Twig_TestInterface $test A Twig_TestInterface instance
-     */
-    public function addTest($name, Twig_TestInterface $test)
-    {
-        $this->staging['tests'][$name] = $test;
-        $this->tests = null;
+     * @param string|Twig_SimpleTest             $name The test name or a Twig_SimpleTest instance
+     * @param Twig_TestInterface|Twig_SimpleTest $test A Twig_TestInterface instance or a Twig_SimpleTest instance
+     */
+    public function addTest($name, $test = null)
+    {
+        if ($this->extensionInitialized) {
+            throw new LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name));
+        }
+
+        if (!$name instanceof Twig_SimpleTest && !($test instanceof Twig_SimpleTest || $test instanceof Twig_TestInterface)) {
+            throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest');
+        }
+
+        if ($name instanceof Twig_SimpleTest) {
+            $test = $name;
+            $name = $test->getName();
+        }
+
+        $this->staging->addTest($name, $test);
     }
 
@@ -873,12 +870,6 @@
     public function getTests()
     {
-        if (null === $this->tests) {
-            foreach ($this->getExtensions() as $extension) {
-                foreach ($extension->getTests() as $name => $test) {
-                    $this->addTest($name, $test);
-                }
-            }
-
-            $this->tests = $this->staging['tests'];
+        if (!$this->extensionInitialized) {
+            $this->initExtensions();
         }
 
@@ -887,13 +878,45 @@
 
     /**
+     * Gets a test by name.
+     *
+     * @param string $name The test name
+     *
+     * @return Twig_Test|false A Twig_Test instance or false if the test does not exist
+     */
+    public function getTest($name)
+    {
+        if (!$this->extensionInitialized) {
+            $this->initExtensions();
+        }
+
+        if (isset($this->tests[$name])) {
+            return $this->tests[$name];
+        }
+
+        return false;
+    }
+
+    /**
      * Registers a Function.
      *
-     * @param string                 $name     The function name
-     * @param Twig_FunctionInterface $function A Twig_FunctionInterface instance
-     */
-    public function addFunction($name, Twig_FunctionInterface $function)
-    {
-        $this->staging['functions'][$name] = $function;
-        $this->functions = null;
+     * @param string|Twig_SimpleFunction                 $name     The function name or a Twig_SimpleFunction instance
+     * @param Twig_FunctionInterface|Twig_SimpleFunction $function A Twig_FunctionInterface instance or a Twig_SimpleFunction instance
+     */
+    public function addFunction($name, $function = null)
+    {
+        if ($this->extensionInitialized) {
+            throw new LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name));
+        }
+
+        if (!$name instanceof Twig_SimpleFunction && !($function instanceof Twig_SimpleFunction || $function instanceof Twig_FunctionInterface)) {
+            throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction');
+        }
+
+        if ($name instanceof Twig_SimpleFunction) {
+            $function = $name;
+            $name = $function->getName();
+        }
+
+        $this->staging->addFunction($name, $function);
     }
 
@@ -906,10 +929,10 @@
      * @param string $name function name
      *
-     * @return Twig_Function|false A Twig_Function instance or false if the function does not exists
+     * @return Twig_Function|false A Twig_Function instance or false if the function does not exist
      */
     public function getFunction($name)
     {
-        if (null === $this->functions) {
-            $this->getFunctions();
+        if (!$this->extensionInitialized) {
+            $this->initExtensions();
         }
 
@@ -956,12 +979,6 @@
     public function getFunctions()
     {
-        if (null === $this->functions) {
-            foreach ($this->getExtensions() as $extension) {
-                foreach ($extension->getFunctions() as $name => $function) {
-                    $this->addFunction($name, $function);
-                }
-            }
-
-            $this->functions = $this->staging['functions'];
+        if (!$this->extensionInitialized) {
+            $this->initExtensions();
         }
 
@@ -971,4 +988,7 @@
     /**
      * Registers a Global.
+     *
+     * New globals can be added before compiling or rendering a template;
+     * but after, you can only update existing globals.
      *
      * @param string $name  The global name
@@ -977,6 +997,22 @@
     public function addGlobal($name, $value)
     {
-        $this->staging['globals'][$name] = $value;
-        $this->globals = null;
+        if ($this->extensionInitialized || $this->runtimeInitialized) {
+            if (null === $this->globals) {
+                $this->globals = $this->initGlobals();
+            }
+
+            /* This condition must be uncommented in Twig 2.0
+            if (!array_key_exists($name, $this->globals)) {
+                throw new LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name));
+            }
+            */
+        }
+
+        if ($this->extensionInitialized || $this->runtimeInitialized) {
+            // update the value
+            $this->globals[$name] = $value;
+        } else {
+            $this->staging->addGlobal($name, $value);
+        }
     }
 
@@ -988,9 +1024,10 @@
     public function getGlobals()
     {
+        if (!$this->runtimeInitialized && !$this->extensionInitialized) {
+            return $this->initGlobals();
+        }
+
         if (null === $this->globals) {
-            $this->globals = isset($this->staging['globals']) ? $this->staging['globals'] : array();
-            foreach ($this->getExtensions() as $extension) {
-                $this->globals = array_merge($this->globals, $extension->getGlobals());
-            }
+            $this->globals = $this->initGlobals();
         }
 
@@ -1025,6 +1062,6 @@
     public function getUnaryOperators()
     {
-        if (null === $this->unaryOperators) {
-            $this->initOperators();
+        if (!$this->extensionInitialized) {
+            $this->initExtensions();
         }
 
@@ -1039,6 +1076,6 @@
     public function getBinaryOperators()
     {
-        if (null === $this->binaryOperators) {
-            $this->initOperators();
+        if (!$this->extensionInitialized) {
+            $this->initExtensions();
         }
 
@@ -1060,15 +1097,91 @@
     }
 
-    protected function initOperators()
-    {
+    protected function initGlobals()
+    {
+        $globals = array();
+        foreach ($this->extensions as $extension) {
+            $globals = array_merge($globals, $extension->getGlobals());
+        }
+
+        return array_merge($globals, $this->staging->getGlobals());
+    }
+
+    protected function initExtensions()
+    {
+        if ($this->extensionInitialized) {
+            return;
+        }
+
+        $this->extensionInitialized = true;
+        $this->parsers = new Twig_TokenParserBroker();
+        $this->filters = array();
+        $this->functions = array();
+        $this->tests = array();
+        $this->visitors = array();
         $this->unaryOperators = array();
         $this->binaryOperators = array();
-        foreach ($this->getExtensions() as $extension) {
-            $operators = $extension->getOperators();
-
-            if (!$operators) {
-                continue;
-            }
-
+
+        foreach ($this->extensions as $extension) {
+            $this->initExtension($extension);
+        }
+        $this->initExtension($this->staging);
+    }
+
+    protected function initExtension(Twig_ExtensionInterface $extension)
+    {
+        // filters
+        foreach ($extension->getFilters() as $name => $filter) {
+            if ($name instanceof Twig_SimpleFilter) {
+                $filter = $name;
+                $name = $filter->getName();
+            } elseif ($filter instanceof Twig_SimpleFilter) {
+                $name = $filter->getName();
+            }
+
+            $this->filters[$name] = $filter;
+        }
+
+        // functions
+        foreach ($extension->getFunctions() as $name => $function) {
+            if ($name instanceof Twig_SimpleFunction) {
+                $function = $name;
+                $name = $function->getName();
+            } elseif ($function instanceof Twig_SimpleFunction) {
+                $name = $function->getName();
+            }
+
+            $this->functions[$name] = $function;
+        }
+
+        // tests
+        foreach ($extension->getTests() as $name => $test) {
+            if ($name instanceof Twig_SimpleTest) {
+                $test = $name;
+                $name = $test->getName();
+            } elseif ($test instanceof Twig_SimpleTest) {
+                $name = $test->getName();
+            }
+
+            $this->tests[$name] = $test;
+        }
+
+        // token parsers
+        foreach ($extension->getTokenParsers() as $parser) {
+            if ($parser instanceof Twig_TokenParserInterface) {
+                $this->parsers->addTokenParser($parser);
+            } elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
+                $this->parsers->addTokenParserBroker($parser);
+            } else {
+                throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances');
+            }
+        }
+
+        // node visitors
+        foreach ($extension->getNodeVisitors() as $visitor) {
+            $this->visitors[] = $visitor;
+        }
+
+        // operators
+        if ($operators = $extension->getOperators()) {
             if (2 !== count($operators)) {
                 throw new InvalidArgumentException(sprintf('"%s::getOperators()" does not return a valid operators array.', get_class($extension)));
Index: inc/libs/twig/ExistsLoaderInterface.php
===================================================================
--- inc/libs/twig/ExistsLoaderInterface.php	(revision 991)
+++ inc/libs/twig/ExistsLoaderInterface.php	(revision 1101)
@@ -15,4 +15,5 @@
  * @package    twig
  * @author     Florin Patan <florinpatan@gmail.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 interface Twig_ExistsLoaderInterface
Index: inc/libs/twig/ExpressionParser.php
===================================================================
--- inc/libs/twig/ExpressionParser.php	(revision 991)
+++ inc/libs/twig/ExpressionParser.php	(revision 1101)
@@ -90,7 +90,17 @@
         while ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '?')) {
             $this->parser->getStream()->next();
-            $expr2 = $this->parseExpression();
-            $this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'The ternary operator must have a default value');
-            $expr3 = $this->parseExpression();
+            if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
+                $expr2 = $this->parseExpression();
+                if ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
+                    $this->parser->getStream()->next();
+                    $expr3 = $this->parseExpression();
+                } else {
+                    $expr3 = new Twig_Node_Expression_Constant('', $this->parser->getCurrentToken()->getLine());
+                }
+            } else {
+                $this->parser->getStream()->next();
+                $expr2 = $expr;
+                $expr3 = $this->parseExpression();
+            }
 
             $expr = new Twig_Node_Expression_Conditional($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine());
@@ -288,7 +298,7 @@
     public function getFunctionNode($name, $line)
     {
-        $args = $this->parseArguments();
         switch ($name) {
             case 'parent':
+                $args = $this->parseArguments();
                 if (!count($this->parser->getBlockStack())) {
                     throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line, $this->parser->getFilename());
@@ -301,6 +311,7 @@
                 return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line);
             case 'block':
-                return new Twig_Node_Expression_BlockReference($args->getNode(0), false, $line);
+                return new Twig_Node_Expression_BlockReference($this->parseArguments()->getNode(0), false, $line);
             case 'attribute':
+                $args = $this->parseArguments();
                 if (count($args) < 2) {
                     throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line, $this->parser->getFilename());
@@ -311,5 +322,5 @@
                 if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
                     $arguments = new Twig_Node_Expression_Array(array(), $line);
-                    foreach ($args as $n) {
+                    foreach ($this->parseArguments() as $n) {
                         $arguments->addElement($n);
                     }
@@ -321,5 +332,6 @@
                 }
 
-                $class = $this->getFunctionNodeClass($name);
+                $args = $this->parseArguments(true);
+                $class = $this->getFunctionNodeClass($name, $line);
 
                 return new $class($name, $args, $line);
@@ -354,13 +366,33 @@
                 throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename());
             }
+
+            if ($node instanceof Twig_Node_Expression_Name && null !== $alias = $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
+                if (!$arg instanceof Twig_Node_Expression_Constant) {
+                    throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename());
+                }
+
+                $node = new Twig_Node_Expression_MethodCall($node, 'get'.$arg->getAttribute('value'), $arguments, $lineno);
+                $node->setAttribute('safe', true);
+
+                return $node;
+            }
         } else {
             $type = Twig_TemplateInterface::ARRAY_CALL;
 
-            $arg = $this->parseExpression();
-
             // slice?
+            $slice = false;
             if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
+                $slice = true;
+                $arg = new Twig_Node_Expression_Constant(0, $token->getLine());
+            } else {
+                $arg = $this->parseExpression();
+            }
+
+            if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
+                $slice = true;
                 $stream->next();
-
+            }
+
+            if ($slice) {
                 if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
                     $length = new Twig_Node_Expression_Constant(null, $token->getLine());
@@ -369,5 +401,5 @@
                 }
 
-                $class = $this->getFilterNodeClass('slice');
+                $class = $this->getFilterNodeClass('slice', $token->getLine());
                 $arguments = new Twig_Node(array($arg, $length));
                 $filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine());
@@ -379,11 +411,4 @@
 
             $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']');
-        }
-
-        if ($node instanceof Twig_Node_Expression_Name && null !== $alias = $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
-            $node = new Twig_Node_Expression_MethodCall($node, 'get'.$arg->getAttribute('value'), $arguments, $lineno);
-            $node->setAttribute('safe', true);
-
-            return $node;
         }
 
@@ -407,8 +432,8 @@
                 $arguments = new Twig_Node();
             } else {
-                $arguments = $this->parseArguments();
-            }
-
-            $class = $this->getFilterNodeClass($name->getAttribute('value'));
+                $arguments = $this->parseArguments(true);
+            }
+
+            $class = $this->getFilterNodeClass($name->getAttribute('value'), $token->getLine());
 
             $node = new $class($node, $name, $arguments, $token->getLine(), $tag);
@@ -424,15 +449,60 @@
     }
 
-    public function parseArguments()
+    /**
+     * Parses arguments.
+     *
+     * @param Boolean $namedArguments Whether to allow named arguments or not
+     * @param Boolean $definition     Whether we are parsing arguments for a function definition
+     */
+    public function parseArguments($namedArguments = false, $definition = false)
     {
         $args = array();
         $stream = $this->parser->getStream();
 
-        $stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must be opened by a parenthesis');
+        $stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis');
         while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ')')) {
             if (!empty($args)) {
                 $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma');
             }
-            $args[] = $this->parseExpression();
+
+            if ($definition) {
+                $token = $stream->expect(Twig_Token::NAME_TYPE, null, 'An argument must be a name');
+                $value = new Twig_Node_Expression_Name($token->getValue(), $this->parser->getCurrentToken()->getLine());
+            } else {
+                $value = $this->parseExpression();
+            }
+
+            $name = null;
+            if ($namedArguments && $stream->test(Twig_Token::OPERATOR_TYPE, '=')) {
+                $token = $stream->next();
+                if (!$value instanceof Twig_Node_Expression_Name) {
+                    throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given', get_class($value)), $token->getLine(), $this->parser->getFilename());
+                }
+                $name = $value->getAttribute('name');
+
+                if ($definition) {
+                    $value = $this->parsePrimaryExpression();
+
+                    if (!$this->checkConstantExpression($value)) {
+                        throw new Twig_Error_Syntax(sprintf('A default value for an argument must be a constant (a boolean, a string, a number, or an array).'), $token->getLine(), $this->parser->getFilename());
+                    }
+                } else {
+                    $value = $this->parseExpression();
+                }
+            }
+
+            if ($definition) {
+                if (null === $name) {
+                    $name = $value->getAttribute('name');
+                    $value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine());
+                }
+                $args[$name] = $value;
+            } else {
+                if (null === $name) {
+                    $args[] = $value;
+                } else {
+                    $args[$name] = $value;
+                }
+            }
         }
         $stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis');
@@ -474,22 +544,58 @@
     }
 
-    protected function getFunctionNodeClass($name)
-    {
-        $functionMap = $this->parser->getEnvironment()->getFunctions();
-        if (isset($functionMap[$name]) && $functionMap[$name] instanceof Twig_Function_Node) {
-            return $functionMap[$name]->getClass();
-        }
-
-        return 'Twig_Node_Expression_Function';
-    }
-
-    protected function getFilterNodeClass($name)
-    {
-        $filterMap = $this->parser->getEnvironment()->getFilters();
-        if (isset($filterMap[$name]) && $filterMap[$name] instanceof Twig_Filter_Node) {
-            return $filterMap[$name]->getClass();
-        }
-
-        return 'Twig_Node_Expression_Filter';
+    protected function getFunctionNodeClass($name, $line)
+    {
+        $env = $this->parser->getEnvironment();
+
+        if (false === $function = $env->getFunction($name)) {
+            $message = sprintf('The function "%s" does not exist', $name);
+            if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFunctions()))) {
+                $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
+            }
+
+            throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
+        }
+
+        if ($function instanceof Twig_SimpleFunction) {
+            return $function->getNodeClass();
+        }
+
+        return $function instanceof Twig_Function_Node ? $function->getClass() : 'Twig_Node_Expression_Function';
+    }
+
+    protected function getFilterNodeClass($name, $line)
+    {
+        $env = $this->parser->getEnvironment();
+
+        if (false === $filter = $env->getFilter($name)) {
+            $message = sprintf('The filter "%s" does not exist', $name);
+            if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFilters()))) {
+                $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
+            }
+
+            throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
+        }
+
+        if ($filter instanceof Twig_SimpleFilter) {
+            return $filter->getNodeClass();
+        }
+
+        return $filter instanceof Twig_Filter_Node ? $filter->getClass() : 'Twig_Node_Expression_Filter';
+    }
+
+    // checks that the node only contains "constant" elements
+    protected function checkConstantExpression(Twig_NodeInterface $node)
+    {
+        if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array)) {
+            return false;
+        }
+
+        foreach ($node as $n) {
+            if (!$this->checkConstantExpression($n)) {
+                return false;
+            }
+        }
+
+        return true;
     }
 }
Index: inc/libs/twig/Extension/Core.php
===================================================================
--- inc/libs/twig/Extension/Core.php	(revision 991)
+++ inc/libs/twig/Extension/Core.php	(revision 1101)
@@ -127,45 +127,45 @@
         $filters = array(
             // formatting filters
-            'date'          => new Twig_Filter_Function('twig_date_format_filter', array('needs_environment' => true)),
-            'date_modify'   => new Twig_Filter_Function('twig_date_modify_filter', array('needs_environment' => true)),
-            'format'        => new Twig_Filter_Function('sprintf'),
-            'replace'       => new Twig_Filter_Function('strtr'),
-            'number_format' => new Twig_Filter_Function('twig_number_format_filter', array('needs_environment' => true)),
-            'abs'           => new Twig_Filter_Function('abs'),
+            new Twig_SimpleFilter('date', 'twig_date_format_filter', array('needs_environment' => true)),
+            new Twig_SimpleFilter('date_modify', 'twig_date_modify_filter', array('needs_environment' => true)),
+            new Twig_SimpleFilter('format', 'sprintf'),
+            new Twig_SimpleFilter('replace', 'strtr'),
+            new Twig_SimpleFilter('number_format', 'twig_number_format_filter', array('needs_environment' => true)),
+            new Twig_SimpleFilter('abs', 'abs'),
 
             // encoding
-            'url_encode'       => new Twig_Filter_Function('twig_urlencode_filter'),
-            'json_encode'      => new Twig_Filter_Function('twig_jsonencode_filter'),
-            'convert_encoding' => new Twig_Filter_Function('twig_convert_encoding'),
+            new Twig_SimpleFilter('url_encode', 'twig_urlencode_filter'),
+            new Twig_SimpleFilter('json_encode', 'twig_jsonencode_filter'),
+            new Twig_SimpleFilter('convert_encoding', 'twig_convert_encoding'),
 
             // string filters
-            'title'      => new Twig_Filter_Function('twig_title_string_filter', array('needs_environment' => true)),
-            'capitalize' => new Twig_Filter_Function('twig_capitalize_string_filter', array('needs_environment' => true)),
-            'upper'      => new Twig_Filter_Function('strtoupper'),
-            'lower'      => new Twig_Filter_Function('strtolower'),
-            'striptags'  => new Twig_Filter_Function('strip_tags'),
-            'trim'       => new Twig_Filter_Function('trim'),
-            'nl2br'      => new Twig_Filter_Function('nl2br', array('pre_escape' => 'html', 'is_safe' => array('html'))),
+            new Twig_SimpleFilter('title', 'twig_title_string_filter', array('needs_environment' => true)),
+            new Twig_SimpleFilter('capitalize', 'twig_capitalize_string_filter', array('needs_environment' => true)),
+            new Twig_SimpleFilter('upper', 'strtoupper'),
+            new Twig_SimpleFilter('lower', 'strtolower'),
+            new Twig_SimpleFilter('striptags', 'strip_tags'),
+            new Twig_SimpleFilter('trim', 'trim'),
+            new Twig_SimpleFilter('nl2br', 'nl2br', array('pre_escape' => 'html', 'is_safe' => array('html'))),
 
             // array helpers
-            'join'    => new Twig_Filter_Function('twig_join_filter'),
-            'split'   => new Twig_Filter_Function('twig_split_filter'),
-            'sort'    => new Twig_Filter_Function('twig_sort_filter'),
-            'merge'   => new Twig_Filter_Function('twig_array_merge'),
+            new Twig_SimpleFilter('join', 'twig_join_filter'),
+            new Twig_SimpleFilter('split', 'twig_split_filter'),
+            new Twig_SimpleFilter('sort', 'twig_sort_filter'),
+            new Twig_SimpleFilter('merge', 'twig_array_merge'),
 
             // string/array filters
-            'reverse' => new Twig_Filter_Function('twig_reverse_filter', array('needs_environment' => true)),
-            'length'  => new Twig_Filter_Function('twig_length_filter', array('needs_environment' => true)),
-            'slice'   => new Twig_Filter_Function('twig_slice', array('needs_environment' => true)),
+            new Twig_SimpleFilter('reverse', 'twig_reverse_filter', array('needs_environment' => true)),
+            new Twig_SimpleFilter('length', 'twig_length_filter', array('needs_environment' => true)),
+            new Twig_SimpleFilter('slice', 'twig_slice', array('needs_environment' => true)),
+            new Twig_SimpleFilter('first', 'twig_first', array('needs_environment' => true)),
+            new Twig_SimpleFilter('last', 'twig_last', array('needs_environment' => true)),
 
             // iteration and runtime
-            'default' => new Twig_Filter_Node('Twig_Node_Expression_Filter_Default'),
-            '_default' => new Twig_Filter_Function('_twig_default_filter'),
-
-            'keys'    => new Twig_Filter_Function('twig_get_array_keys_filter'),
+            new Twig_SimpleFilter('default', '_twig_default_filter', array('node_class' => 'Twig_Node_Expression_Filter_Default')),
+            new Twig_SimpleFilter('keys', 'twig_get_array_keys_filter'),
 
             // escaping
-            'escape' => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
-            'e'      => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
+            new Twig_SimpleFilter('escape', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
+            new Twig_SimpleFilter('e', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
         );
 
@@ -186,9 +186,10 @@
     {
         return array(
-            'range'    => new Twig_Function_Function('range'),
-            'constant' => new Twig_Function_Function('constant'),
-            'cycle'    => new Twig_Function_Function('twig_cycle'),
-            'random'   => new Twig_Function_Function('twig_random', array('needs_environment' => true)),
-            'date'     => new Twig_Function_Function('twig_date_converter', array('needs_environment' => true)),
+            new Twig_SimpleFunction('range', 'range'),
+            new Twig_SimpleFunction('constant', 'twig_constant'),
+            new Twig_SimpleFunction('cycle', 'twig_cycle'),
+            new Twig_SimpleFunction('random', 'twig_random', array('needs_environment' => true)),
+            new Twig_SimpleFunction('date', 'twig_date_converter', array('needs_environment' => true)),
+            new Twig_SimpleFunction('include', 'twig_include', array('needs_environment' => true, 'needs_context' => true)),
         );
     }
@@ -202,14 +203,14 @@
     {
         return array(
-            'even'        => new Twig_Test_Node('Twig_Node_Expression_Test_Even'),
-            'odd'         => new Twig_Test_Node('Twig_Node_Expression_Test_Odd'),
-            'defined'     => new Twig_Test_Node('Twig_Node_Expression_Test_Defined'),
-            'sameas'      => new Twig_Test_Node('Twig_Node_Expression_Test_Sameas'),
-            'none'        => new Twig_Test_Node('Twig_Node_Expression_Test_Null'),
-            'null'        => new Twig_Test_Node('Twig_Node_Expression_Test_Null'),
-            'divisibleby' => new Twig_Test_Node('Twig_Node_Expression_Test_Divisibleby'),
-            'constant'    => new Twig_Test_Node('Twig_Node_Expression_Test_Constant'),
-            'empty'       => new Twig_Test_Function('twig_test_empty'),
-            'iterable'    => new Twig_Test_Function('twig_test_iterable'),
+            new Twig_SimpleTest('even', null, array('node_class' => 'Twig_Node_Expression_Test_Even')),
+            new Twig_SimpleTest('odd', null, array('node_class' => 'Twig_Node_Expression_Test_Odd')),
+            new Twig_SimpleTest('defined', null, array('node_class' => 'Twig_Node_Expression_Test_Defined')),
+            new Twig_SimpleTest('sameas', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')),
+            new Twig_SimpleTest('none', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
+            new Twig_SimpleTest('null', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
+            new Twig_SimpleTest('divisibleby', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')),
+            new Twig_SimpleTest('constant', null, array('node_class' => 'Twig_Node_Expression_Test_Constant')),
+            new Twig_SimpleTest('empty', 'twig_test_empty'),
+            new Twig_SimpleTest('iterable', 'twig_test_iterable'),
         );
     }
@@ -268,20 +269,30 @@
         $arguments = null;
         if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
-            $arguments = $parser->getExpressionParser()->parseArguments();
-        }
-
-        $class = $this->getTestNodeClass($parser->getEnvironment(), $name);
+            $arguments = $parser->getExpressionParser()->parseArguments(true);
+        }
+
+        $class = $this->getTestNodeClass($parser, $name, $node->getLine());
 
         return new $class($node, $name, $arguments, $parser->getCurrentToken()->getLine());
     }
 
-    protected function getTestNodeClass(Twig_Environment $env, $name)
-    {
+    protected function getTestNodeClass(Twig_Parser $parser, $name, $line)
+    {
+        $env = $parser->getEnvironment();
         $testMap = $env->getTests();
-        if (isset($testMap[$name]) && $testMap[$name] instanceof Twig_Test_Node) {
-            return $testMap[$name]->getClass();
-        }
-
-        return 'Twig_Node_Expression_Test';
+        if (!isset($testMap[$name])) {
+            $message = sprintf('The test "%s" does not exist', $name);
+            if ($alternatives = $env->computeAlternatives($name, array_keys($env->getTests()))) {
+                $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
+            }
+
+            throw new Twig_Error_Syntax($message, $line, $parser->getFilename());
+        }
+
+        if ($testMap[$name] instanceof Twig_SimpleTest) {
+            return $testMap[$name]->getNodeClass();
+        }
+
+        return $testMap[$name] instanceof Twig_Test_Node ? $testMap[$name]->getClass() : 'Twig_Node_Expression_Test';
     }
 
@@ -300,10 +311,10 @@
  * Cycles over a value.
  *
- * @param ArrayAccess|array $values An array or an ArrayAccess instance
- * @param integer           $i      The cycle value
+ * @param ArrayAccess|array $values   An array or an ArrayAccess instance
+ * @param integer           $position The cycle position
  *
  * @return string The next value in the cycle
  */
-function twig_cycle($values, $i)
+function twig_cycle($values, $position)
 {
     if (!is_array($values) && !$values instanceof ArrayAccess) {
@@ -311,5 +322,5 @@
     }
 
-    return $values[$i % count($values)];
+    return $values[$position % count($values)];
 }
 
@@ -405,5 +416,5 @@
  *
  * <pre>
- *   {{ post.published_at|modify("-1day")|date("m/d/Y") }}
+ *   {{ post.published_at|date_modify("-1day")|date("m/d/Y") }}
  * </pre>
  *
@@ -459,11 +470,13 @@
     $asString = (string) $date;
     if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
-        $date = new DateTime('@'.$date);
+        $date = '@'.$date;
+    }
+
+    $date = new DateTime($date, $defaultTimezone);
+    if (false !== $timezone) {
         $date->setTimezone($defaultTimezone);
-
-        return $date;
-    }
-
-    return new DateTime($date, $defaultTimezone);
+    }
+
+    return $date;
 }
 
@@ -621,4 +634,34 @@
 
 /**
+ * Returns the first element of the item.
+ *
+ * @param Twig_Environment $env  A Twig_Environment instance
+ * @param mixed            $item A variable
+ *
+ * @return mixed The first element of the item
+ */
+function twig_first(Twig_Environment $env, $item)
+{
+    $elements = twig_slice($env, $item, 0, 1, false);
+
+    return is_string($elements) ? $elements[0] : current($elements);
+}
+
+/**
+ * Returns the last element of the item.
+ *
+ * @param Twig_Environment $env  A Twig_Environment instance
+ * @param mixed            $item A variable
+ *
+ * @return mixed The last element of the item
+ */
+function twig_last(Twig_Environment $env, $item)
+{
+    $elements = twig_slice($env, $item, -1, 1, false);
+
+    return is_string($elements) ? $elements[0] : current($elements);
+}
+
+/**
  * Joins the values to a string.
  *
@@ -774,16 +817,14 @@
 function twig_in_filter($value, $compare)
 {
-    $strict = is_object($value);
-
     if (is_array($compare)) {
-        return in_array($value, $compare, $strict);
+        return in_array($value, $compare, is_object($value));
     } elseif (is_string($compare)) {
-        if (!strlen((string) $value)) {
+        if (!strlen($value)) {
             return empty($compare);
         }
 
         return false !== strpos($compare, (string) $value);
-    } elseif (is_object($compare) && $compare instanceof Traversable) {
-        return in_array($value, iterator_to_array($compare, false), $strict);
+    } elseif ($compare instanceof Traversable) {
+        return in_array($value, iterator_to_array($compare, false), is_object($value));
     }
 
@@ -1192,5 +1233,5 @@
     }
 
-    return false === $value || (empty($value) && '0' != $value);
+    return '' === $value || false === $value || null === $value || array() === $value;
 }
 
@@ -1213,2 +1254,56 @@
     return $value instanceof Traversable || is_array($value);
 }
+
+/**
+ * Renders a template.
+ *
+ * @param string  template       The template to render
+ * @param array   variables      The variables to pass to the template
+ * @param Boolean with_context   Whether to pass the current context variables or not
+ * @param Boolean ignore_missing Whether to ignore missing templates or not
+ * @param Boolean sandboxed      Whether to sandbox the template or not
+ *
+ * @return string The rendered template
+ */
+function twig_include(Twig_Environment $env, $context, $template, $variables = array(), $withContext = true, $ignoreMissing = false, $sandboxed = false)
+{
+    if ($withContext) {
+        $variables = array_merge($context, $variables);
+    }
+
+    if ($isSandboxed = $sandboxed && $env->hasExtension('sandbox')) {
+        $sandbox = $env->getExtension('sandbox');
+        if (!$alreadySandboxed = $sandbox->isSandboxed()) {
+            $sandbox->enableSandbox();
+        }
+    }
+
+    try {
+        return $env->resolveTemplate($template)->display($variables);
+    } catch (Twig_Error_Loader $e) {
+        if (!$ignoreMissing) {
+            throw $e;
+        }
+    }
+
+    if ($isSandboxed && !$alreadySandboxed) {
+        $sandbox->disableSandbox();
+    }
+}
+
+/**
+ * Provides the ability to get constants from instances as well as class/global constants.
+ *
+ * @param string      $constant The name of the constant
+ * @param null|object $object   The object to get the constant from
+ *
+ * @return string
+ */
+function twig_constant($constant, $object = null)
+{
+    if (null !== $object) {
+        $constant = get_class($object).'::'.$constant;
+    }
+
+    return constant($constant);
+}
Index: inc/libs/twig/Extension/Debug.php
===================================================================
--- inc/libs/twig/Extension/Debug.php	(revision 991)
+++ inc/libs/twig/Extension/Debug.php	(revision 1101)
@@ -28,5 +28,5 @@
 
         return array(
-            'dump' => new Twig_Function_Function('twig_var_dump', array('is_safe' => $isDumpOutputHtmlSafe ? array('html') : array(), 'needs_context' => true, 'needs_environment' => true)),
+            new Twig_SimpleFunction('dump', 'twig_var_dump', array('is_safe' => $isDumpOutputHtmlSafe ? array('html') : array(), 'needs_context' => true, 'needs_environment' => true)),
         );
     }
Index: inc/libs/twig/Extension/Escaper.php
===================================================================
--- inc/libs/twig/Extension/Escaper.php	(revision 991)
+++ inc/libs/twig/Extension/Escaper.php	(revision 1101)
@@ -46,5 +46,5 @@
     {
         return array(
-            'raw' => new Twig_Filter_Function('twig_raw_filter', array('is_safe' => array('all'))),
+            new Twig_SimpleFilter('raw', 'twig_raw_filter', array('is_safe' => array('all'))),
         );
     }
Index: inc/libs/twig/Extension/Staging.php
===================================================================
--- inc/libs/twig/Extension/Staging.php	(revision 1101)
+++ inc/libs/twig/Extension/Staging.php	(revision 1101)
@@ -0,0 +1,114 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2012 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Internal class.
+ *
+ * This class is used by Twig_Environment as a staging area and must not be used directly.
+ *
+ * @package twig
+ * @author  Fabien Potencier <fabien@symfony.com>
+ */
+class Twig_Extension_Staging extends Twig_Extension
+{
+    protected $functions = array();
+    protected $filters = array();
+    protected $visitors = array();
+    protected $tokenParsers = array();
+    protected $globals = array();
+    protected $tests = array();
+
+    public function addFunction($name, $function)
+    {
+        $this->functions[$name] = $function;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getFunctions()
+    {
+        return $this->functions;
+    }
+
+    public function addFilter($name, $filter)
+    {
+        $this->filters[$name] = $filter;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getFilters()
+    {
+        return $this->filters;
+    }
+
+    public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
+    {
+        $this->visitors[] = $visitor;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getNodeVisitors()
+    {
+        return $this->visitors;
+    }
+
+    public function addTokenParser(Twig_TokenParserInterface $parser)
+    {
+        $this->tokenParsers[] = $parser;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getTokenParsers()
+    {
+        return $this->tokenParsers;
+    }
+
+    public function addGlobal($name, $value)
+    {
+        $this->globals[$name] = $value;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getGlobals()
+    {
+        return $this->globals;
+    }
+
+    public function addTest($name, $test)
+    {
+        $this->tests[$name] = $test;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getTests()
+    {
+        return $this->tests;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getName()
+    {
+        return 'staging';
+    }
+}
Index: inc/libs/twig/Extension/StringLoader.php
===================================================================
--- inc/libs/twig/Extension/StringLoader.php	(revision 991)
+++ inc/libs/twig/Extension/StringLoader.php	(revision 1101)
@@ -17,5 +17,5 @@
     {
         return array(
-            'template_from_string' => new Twig_Function_Function('twig_template_from_string', array('needs_environment' => true)),
+            new Twig_SimpleFunction('template_from_string', 'twig_template_from_string', array('needs_environment' => true)),
         );
     }
Index: inc/libs/twig/Filter.php
===================================================================
--- inc/libs/twig/Filter.php	(revision 991)
+++ inc/libs/twig/Filter.php	(revision 1101)
@@ -13,8 +13,11 @@
  * Represents a template filter.
  *
+ * Use Twig_SimpleFilter instead.
+ *
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
-abstract class Twig_Filter implements Twig_FilterInterface
+abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface
 {
     protected $options;
@@ -28,4 +31,5 @@
             'pre_escape'        => null,
             'preserves_safety'  => null,
+            'callable'          => null,
         ), $options);
     }
@@ -73,3 +77,8 @@
         return $this->options['pre_escape'];
     }
+
+    public function getCallable()
+    {
+        return $this->options['callable'];
+    }
 }
Index: inc/libs/twig/Filter/Function.php
===================================================================
--- inc/libs/twig/Filter/Function.php	(revision 991)
+++ inc/libs/twig/Filter/Function.php	(revision 1101)
@@ -13,6 +13,9 @@
  * Represents a function template filter.
  *
+ * Use Twig_SimpleFilter instead.
+ *
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 class Twig_Filter_Function extends Twig_Filter
@@ -22,4 +25,6 @@
     public function __construct($function, array $options = array())
     {
+        $options['callable'] = $function;
+
         parent::__construct($options);
 
Index: inc/libs/twig/Filter/Method.php
===================================================================
--- inc/libs/twig/Filter/Method.php	(revision 991)
+++ inc/libs/twig/Filter/Method.php	(revision 1101)
@@ -13,6 +13,9 @@
  * Represents a method template filter.
  *
+ * Use Twig_SimpleFilter instead.
+ *
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 class Twig_Filter_Method extends Twig_Filter
@@ -23,4 +26,6 @@
     public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
     {
+        $options['callable'] = array($extension, $method);
+
         parent::__construct($options);
 
Index: inc/libs/twig/Filter/Node.php
===================================================================
--- inc/libs/twig/Filter/Node.php	(revision 991)
+++ inc/libs/twig/Filter/Node.php	(revision 1101)
@@ -13,6 +13,9 @@
  * Represents a template filter as a node.
  *
+ * Use Twig_SimpleFilter instead.
+ *
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 class Twig_Filter_Node extends Twig_Filter
Index: inc/libs/twig/FilterCallableInterface.php
===================================================================
--- inc/libs/twig/FilterCallableInterface.php	(revision 1101)
+++ inc/libs/twig/FilterCallableInterface.php	(revision 1101)
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2012 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a callable template filter.
+ *
+ * Use Twig_SimpleFilter instead.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
+ */
+interface Twig_FilterCallableInterface
+{
+    public function getCallable();
+}
Index: inc/libs/twig/FilterInterface.php
===================================================================
--- inc/libs/twig/FilterInterface.php	(revision 991)
+++ inc/libs/twig/FilterInterface.php	(revision 1101)
@@ -13,6 +13,9 @@
  * Represents a template filter.
  *
+ * Use Twig_SimpleFilter instead.
+ *
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 interface Twig_FilterInterface
Index: inc/libs/twig/Function.php
===================================================================
--- inc/libs/twig/Function.php	(revision 991)
+++ inc/libs/twig/Function.php	(revision 1101)
@@ -13,8 +13,11 @@
  * Represents a template function.
  *
+ * Use Twig_SimpleFunction instead.
+ *
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
-abstract class Twig_Function implements Twig_FunctionInterface
+abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface
 {
     protected $options;
@@ -26,4 +29,5 @@
             'needs_environment' => false,
             'needs_context'     => false,
+            'callable'          => null,
         ), $options);
     }
@@ -61,3 +65,8 @@
         return array();
     }
+
+    public function getCallable()
+    {
+        return $this->options['callable'];
+    }
 }
Index: inc/libs/twig/Function/Function.php
===================================================================
--- inc/libs/twig/Function/Function.php	(revision 0)
+++ inc/libs/twig/Function/Function.php	(revision 1101)
@@ -14,6 +14,9 @@
  * Represents a function template function.
  *
+ * Use Twig_SimpleFunction instead.
+ *
  * @package    twig
  * @author     Arnaud Le Blanc <arnaud.lb@gmail.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 class Twig_Function_Function extends Twig_Function
@@ -23,4 +26,6 @@
     public function __construct($function, array $options = array())
     {
+        $options['callable'] = $function;
+
         parent::__construct($options);
 
Index: inc/libs/twig/Function/Method.php
===================================================================
--- inc/libs/twig/Function/Method.php	(revision 991)
+++ inc/libs/twig/Function/Method.php	(revision 1101)
@@ -14,6 +14,9 @@
  * Represents a method template function.
  *
+ * Use Twig_SimpleFunction instead.
+ *
  * @package    twig
  * @author     Arnaud Le Blanc <arnaud.lb@gmail.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 class Twig_Function_Method extends Twig_Function
@@ -24,4 +27,6 @@
     public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
     {
+        $options['callable'] = array($extension, $method);
+
         parent::__construct($options);
 
Index: inc/libs/twig/Function/Node.php
===================================================================
--- inc/libs/twig/Function/Node.php	(revision 991)
+++ inc/libs/twig/Function/Node.php	(revision 1101)
@@ -13,6 +13,9 @@
  * Represents a template function as a node.
  *
+ * Use Twig_SimpleFunction instead.
+ *
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 class Twig_Function_Node extends Twig_Function
Index: inc/libs/twig/FunctionCallableInterface.php
===================================================================
--- inc/libs/twig/FunctionCallableInterface.php	(revision 1101)
+++ inc/libs/twig/FunctionCallableInterface.php	(revision 1101)
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2012 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a callable template function.
+ *
+ * Use Twig_SimpleFunction instead.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
+ */
+interface Twig_FunctionCallableInterface
+{
+    public function getCallable();
+}
Index: inc/libs/twig/FunctionInterface.php
===================================================================
--- inc/libs/twig/FunctionInterface.php	(revision 991)
+++ inc/libs/twig/FunctionInterface.php	(revision 1101)
@@ -14,6 +14,9 @@
  * Represents a template function.
  *
+ * Use Twig_SimpleFunction instead.
+ *
  * @package    twig
  * @author     Arnaud Le Blanc <arnaud.lb@gmail.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 interface Twig_FunctionInterface
Index: inc/libs/twig/LICENSE
===================================================================
--- inc/libs/twig/LICENSE	(revision 0)
+++ inc/libs/twig/LICENSE	(revision 1101)
@@ -1,3 +1,3 @@
-Copyright (c) 2009 by the Twig Team, see AUTHORS for more details.
+Copyright (c) 2009-2013 by the Twig Team, see AUTHORS for more details.
 
 Some rights reserved.
Index: inc/libs/twig/Lexer.php
===================================================================
--- inc/libs/twig/Lexer.php	(revision 991)
+++ inc/libs/twig/Lexer.php	(revision 1101)
@@ -62,8 +62,8 @@
             'lex_var'             => '/\s*'.preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A',
             'lex_block'           => '/\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')\n?/A',
-            'lex_raw_data'        => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*endraw\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s',
+            'lex_raw_data'        => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*(?:end%s)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s',
             'operator'            => $this->getOperatorRegex(),
             'lex_comment'         => '/(?:'.preg_quote($this->options['whitespace_trim'], '/').preg_quote($this->options['tag_comment'][1], '/').'\s*|'.preg_quote($this->options['tag_comment'][1], '/').')\n?/s',
-            'lex_block_raw'       => '/\s*raw\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As',
+            'lex_block_raw'       => '/\s*(raw|verbatim)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As',
             'lex_block_line'      => '/\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '/').'/As',
             'lex_tokens_start'    => '/('.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').'|'.preg_quote($this->options['tag_comment'][0], '/').')('.preg_quote($this->options['whitespace_trim'], '/').')?/s',
@@ -179,5 +179,5 @@
                 if (preg_match($this->regexes['lex_block_raw'], $this->code, $match, null, $this->cursor)) {
                     $this->moveCursor($match[0]);
-                    $this->lexRawData();
+                    $this->lexRawData($match[1]);
                 // {% line \d+ %}
                 } elseif (preg_match($this->regexes['lex_block_line'], $this->code, $match, null, $this->cursor)) {
@@ -287,8 +287,8 @@
     }
 
-    protected function lexRawData()
-    {
-        if (!preg_match($this->regexes['lex_raw_data'], $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
-            throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "block"'), $this->lineno, $this->filename);
+    protected function lexRawData($tag)
+    {
+        if (!preg_match(str_replace('%s', $tag, $this->regexes['lex_raw_data']), $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
+            throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "%s" block', $tag), $this->lineno, $this->filename);
         }
 
Index: inc/libs/twig/LexerInterface.php
===================================================================
--- inc/libs/twig/LexerInterface.php	(revision 991)
+++ inc/libs/twig/LexerInterface.php	(revision 1101)
@@ -15,4 +15,5 @@
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 interface Twig_LexerInterface
Index: inc/libs/twig/Node/Expression/Call.php
===================================================================
--- inc/libs/twig/Node/Expression/Call.php	(revision 1101)
+++ inc/libs/twig/Node/Expression/Call.php	(revision 1101)
@@ -0,0 +1,171 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2012 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
+{
+    protected function compileCallable(Twig_Compiler $compiler)
+    {
+        $callable = $this->getAttribute('callable');
+
+        $closingParenthesis = false;
+        if ($callable) {
+            if (is_string($callable)) {
+                $compiler->raw($callable);
+            } elseif (is_array($callable) && $callable[0] instanceof Twig_ExtensionInterface) {
+                $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', $callable[0]->getName(), $callable[1]));
+            } else {
+                $type = ucfirst($this->getAttribute('type'));
+                $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name')));
+                $closingParenthesis = true;
+            }
+        } else {
+            $compiler->raw($this->getAttribute('thing')->compile());
+        }
+
+        $this->compileArguments($compiler);
+
+        if ($closingParenthesis) {
+            $compiler->raw(')');
+        }
+    }
+
+    protected function compileArguments(Twig_Compiler $compiler)
+    {
+        $compiler->raw('(');
+
+        $first = true;
+
+        if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
+            $compiler->raw('$this->env');
+            $first = false;
+        }
+
+        if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
+            if (!$first) {
+                $compiler->raw(', ');
+            }
+            $compiler->raw('$context');
+            $first = false;
+        }
+
+        if ($this->hasAttribute('arguments')) {
+            foreach ($this->getAttribute('arguments') as $argument) {
+                if (!$first) {
+                    $compiler->raw(', ');
+                }
+                $compiler->string($argument);
+                $first = false;
+            }
+        }
+
+        if ($this->hasNode('node')) {
+            if (!$first) {
+                $compiler->raw(', ');
+            }
+            $compiler->subcompile($this->getNode('node'));
+            $first = false;
+        }
+
+        if ($this->hasNode('arguments') && null !== $this->getNode('arguments')) {
+            $callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null;
+
+            $arguments = $this->getArguments($callable, $this->getNode('arguments'));
+
+            foreach ($arguments as $node) {
+                if (!$first) {
+                    $compiler->raw(', ');
+                }
+                $compiler->subcompile($node);
+                $first = false;
+            }
+        }
+
+        $compiler->raw(')');
+    }
+
+    protected function getArguments($callable, $arguments)
+    {
+        $parameters = array();
+        $named = false;
+        foreach ($arguments as $name => $node) {
+            if (!is_int($name)) {
+                $named = true;
+                $name = $this->normalizeName($name);
+            }
+            $parameters[$name] = $node;
+        }
+
+        if (!$named) {
+            return $parameters;
+        }
+
+        if (!$callable) {
+            throw new LogicException(sprintf('Named arguments are not supported for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name')));
+        }
+
+        // manage named arguments
+        if (is_array($callable)) {
+            $r = new ReflectionMethod($callable[0], $callable[1]);
+        } elseif (is_object($callable) && !$callable instanceof Closure) {
+            $r = new ReflectionObject($callable);
+            $r = $r->getMethod('__invoke');
+        } else {
+            $r = new ReflectionFunction($callable);
+        }
+
+        $definition = $r->getParameters();
+        if ($this->hasNode('node')) {
+            array_shift($definition);
+        }
+        if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
+            array_shift($definition);
+        }
+        if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
+            array_shift($definition);
+        }
+        if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) {
+            foreach ($this->getAttribute('arguments') as $argument) {
+                array_shift($definition);
+            }
+        }
+
+        $arguments = array();
+        $pos = 0;
+        foreach ($definition as $param) {
+            $name = $this->normalizeName($param->name);
+
+            if (array_key_exists($name, $parameters)) {
+                $arguments[] = $parameters[$name];
+                unset($parameters[$name]);
+            } elseif (array_key_exists($pos, $parameters)) {
+                $arguments[] = $parameters[$pos];
+                unset($parameters[$pos]);
+                ++$pos;
+            } elseif ($param->isDefaultValueAvailable()) {
+                $arguments[] = new Twig_Node_Expression_Constant($param->getDefaultValue(), -1);
+            } elseif ($param->isOptional()) {
+                break;
+            } else {
+                throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
+            }
+        }
+
+        foreach (array_keys($parameters) as $name) {
+            throw new Twig_Error_Syntax(sprintf('Unknown argument "%s" for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
+        }
+
+        return $arguments;
+    }
+
+    protected function normalizeName($name)
+    {
+        return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name));
+    }
+}
Index: inc/libs/twig/Node/Expression/Filter.php
===================================================================
--- inc/libs/twig/Node/Expression/Filter.php	(revision 991)
+++ inc/libs/twig/Node/Expression/Filter.php	(revision 1101)
@@ -10,5 +10,5 @@
  * file that was distributed with this source code.
  */
-class Twig_Node_Expression_Filter extends Twig_Node_Expression
+class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call
 {
     public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
@@ -20,42 +20,17 @@
     {
         $name = $this->getNode('filter')->getAttribute('value');
+        $filter = $compiler->getEnvironment()->getFilter($name);
 
-        if (false === $filter = $compiler->getEnvironment()->getFilter($name)) {
-            $message = sprintf('The filter "%s" does not exist', $name);
-            if ($alternatives = $compiler->getEnvironment()->computeAlternatives($name, array_keys($compiler->getEnvironment()->getFilters()))) {
-                $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
-            }
-
-            throw new Twig_Error_Syntax($message, $this->getLine(), $compiler->getFilename());
+        $this->setAttribute('name', $name);
+        $this->setAttribute('type', 'filter');
+        $this->setAttribute('thing', $filter);
+        $this->setAttribute('needs_environment', $filter->needsEnvironment());
+        $this->setAttribute('needs_context', $filter->needsContext());
+        $this->setAttribute('arguments', $filter->getArguments());
+        if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) {
+            $this->setAttribute('callable', $filter->getCallable());
         }
 
-        $this->compileFilter($compiler, $filter);
-    }
-
-    protected function compileFilter(Twig_Compiler $compiler, Twig_FilterInterface $filter)
-    {
-        $compiler
-            ->raw($filter->compile().'(')
-            ->raw($filter->needsEnvironment() ? '$this->env, ' : '')
-            ->raw($filter->needsContext() ? '$context, ' : '')
-        ;
-
-        foreach ($filter->getArguments() as $argument) {
-            $compiler
-                ->string($argument)
-                ->raw(', ')
-            ;
-        }
-
-        $compiler->subcompile($this->getNode('node'));
-
-        foreach ($this->getNode('arguments') as $node) {
-            $compiler
-                ->raw(', ')
-                ->subcompile($node)
-            ;
-        }
-
-        $compiler->raw(')');
+        $this->compileCallable($compiler);
     }
 }
Index: inc/libs/twig/Node/Expression/Filter/Default.php
===================================================================
--- inc/libs/twig/Node/Expression/Filter/Default.php	(revision 991)
+++ inc/libs/twig/Node/Expression/Filter/Default.php	(revision 1101)
@@ -24,5 +24,5 @@
     public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
     {
-        $default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('_default', $node->getLine()), $arguments, $node->getLine());
+        $default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('default', $node->getLine()), $arguments, $node->getLine());
 
         if ('default' === $filterName->getAttribute('value') && ($node instanceof Twig_Node_Expression_Name || $node instanceof Twig_Node_Expression_GetAttr)) {
Index: inc/libs/twig/Node/Expression/Function.php
===================================================================
--- inc/libs/twig/Node/Expression/Function.php	(revision 991)
+++ inc/libs/twig/Node/Expression/Function.php	(revision 1101)
@@ -9,5 +9,5 @@
  * file that was distributed with this source code.
  */
-class Twig_Node_Expression_Function extends Twig_Node_Expression
+class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
 {
     public function __construct($name, Twig_NodeInterface $arguments, $lineno)
@@ -19,48 +19,17 @@
     {
         $name = $this->getAttribute('name');
+        $function = $compiler->getEnvironment()->getFunction($name);
 
-        if (false === $function = $compiler->getEnvironment()->getFunction($name)) {
-            $message = sprintf('The function "%s" does not exist', $name);
-            if ($alternatives = $compiler->getEnvironment()->computeAlternatives($name, array_keys($compiler->getEnvironment()->getFunctions()))) {
-                $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
-            }
-
-            throw new Twig_Error_Syntax($message, $this->getLine(), $compiler->getFilename());
+        $this->setAttribute('name', $name);
+        $this->setAttribute('type', 'function');
+        $this->setAttribute('thing', $function);
+        $this->setAttribute('needs_environment', $function->needsEnvironment());
+        $this->setAttribute('needs_context', $function->needsContext());
+        $this->setAttribute('arguments', $function->getArguments());
+        if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) {
+            $this->setAttribute('callable', $function->getCallable());
         }
 
-        $compiler->raw($function->compile().'(');
-
-        $first = true;
-
-        if ($function->needsEnvironment()) {
-            $compiler->raw('$this->env');
-            $first = false;
-        }
-
-        if ($function->needsContext()) {
-            if (!$first) {
-                $compiler->raw(', ');
-            }
-            $compiler->raw('$context');
-            $first = false;
-        }
-
-        foreach ($function->getArguments() as $argument) {
-            if (!$first) {
-                $compiler->raw(', ');
-            }
-            $compiler->string($argument);
-            $first = false;
-        }
-
-        foreach ($this->getNode('arguments') as $node) {
-            if (!$first) {
-                $compiler->raw(', ');
-            }
-            $compiler->subcompile($node);
-            $first = false;
-        }
-
-        $compiler->raw(')');
+        $this->compileCallable($compiler);
     }
 }
Index: inc/libs/twig/Node/Expression/Test.php
===================================================================
--- inc/libs/twig/Node/Expression/Test.php	(revision 991)
+++ inc/libs/twig/Node/Expression/Test.php	(revision 1101)
@@ -9,5 +9,5 @@
  * file that was distributed with this source code.
  */
-class Twig_Node_Expression_Test extends Twig_Node_Expression
+class Twig_Node_Expression_Test extends Twig_Node_Expression_Call
 {
     public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
@@ -19,36 +19,14 @@
     {
         $name = $this->getAttribute('name');
-        $testMap = $compiler->getEnvironment()->getTests();
-        if (!isset($testMap[$name])) {
-            $message = sprintf('The test "%s" does not exist', $name);
-            if ($alternatives = $compiler->getEnvironment()->computeAlternatives($name, array_keys($compiler->getEnvironment()->getTests()))) {
-                $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
-            }
+        $test = $compiler->getEnvironment()->getTest($name);
 
-            throw new Twig_Error_Syntax($message, $this->getLine(), $compiler->getFilename());
+        $this->setAttribute('name', $name);
+        $this->setAttribute('type', 'test');
+        $this->setAttribute('thing', $test);
+        if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) {
+            $this->setAttribute('callable', $test->getCallable());
         }
 
-        $name = $this->getAttribute('name');
-        $node = $this->getNode('node');
-
-        $compiler
-            ->raw($testMap[$name]->compile().'(')
-            ->subcompile($node)
-        ;
-
-        if (null !== $this->getNode('arguments')) {
-            $compiler->raw(', ');
-
-            $max = count($this->getNode('arguments')) - 1;
-            foreach ($this->getNode('arguments') as $i => $arg) {
-                $compiler->subcompile($arg);
-
-                if ($i != $max) {
-                    $compiler->raw(', ');
-                }
-            }
-        }
-
-        $compiler->raw(')');
+        $this->compileCallable($compiler);
     }
 }
Index: inc/libs/twig/Node/Macro.php
===================================================================
--- inc/libs/twig/Node/Macro.php	(revision 991)
+++ inc/libs/twig/Node/Macro.php	(revision 1101)
@@ -30,12 +30,25 @@
     public function compile(Twig_Compiler $compiler)
     {
-        $arguments = array();
-        foreach ($this->getNode('arguments') as $argument) {
-            $arguments[] = '$_'.$argument->getAttribute('name').' = null';
+        $compiler
+            ->addDebugInfo($this)
+            ->write(sprintf("public function get%s(", $this->getAttribute('name')))
+        ;
+
+        $count = count($this->getNode('arguments'));
+        $pos = 0;
+        foreach ($this->getNode('arguments') as $name => $default) {
+            $compiler
+                ->raw('$_'.$name.' = ')
+                ->subcompile($default)
+            ;
+
+            if (++$pos < $count) {
+                $compiler->raw(', ');
+            }
         }
 
         $compiler
-            ->addDebugInfo($this)
-            ->write(sprintf("public function get%s(%s)\n", $this->getAttribute('name'), implode(', ', $arguments)), "{\n")
+            ->raw(")\n")
+            ->write("{\n")
             ->indent()
         ;
@@ -49,9 +62,9 @@
             ;
 
-            foreach ($this->getNode('arguments') as $argument) {
+            foreach ($this->getNode('arguments') as $name => $default) {
                 $compiler
                     ->write('')
-                    ->string($argument->getAttribute('name'))
-                    ->raw(' => $_'.$argument->getAttribute('name'))
+                    ->string($name)
+                    ->raw(' => $_'.$name)
                     ->raw(",\n")
                 ;
Index: inc/libs/twig/NodeInterface.php
===================================================================
--- inc/libs/twig/NodeInterface.php	(revision 991)
+++ inc/libs/twig/NodeInterface.php	(revision 1101)
@@ -15,4 +15,5 @@
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 interface Twig_NodeInterface extends Countable, IteratorAggregate
Index: inc/libs/twig/NodeVisitor/Escaper.php
===================================================================
--- inc/libs/twig/NodeVisitor/Escaper.php	(revision 991)
+++ inc/libs/twig/NodeVisitor/Escaper.php	(revision 1101)
@@ -108,19 +108,15 @@
         $name = $filter->getNode('filter')->getAttribute('value');
 
-        if (false !== $f = $env->getFilter($name)) {
-            $type = $f->getPreEscape();
-            if (null === $type) {
-                return $filter;
-            }
-
-            $node = $filter->getNode('node');
-            if ($this->isSafeFor($type, $node, $env)) {
-                return $filter;
-            }
-
-            $filter->setNode('node', $this->getEscaperFilter($type, $node));
-
+        $type = $env->getFilter($name)->getPreEscape();
+        if (null === $type) {
             return $filter;
         }
+
+        $node = $filter->getNode('node');
+        if ($this->isSafeFor($type, $node, $env)) {
+            return $filter;
+        }
+
+        $filter->setNode('node', $this->getEscaperFilter($type, $node));
 
         return $filter;
Index: inc/libs/twig/ParserInterface.php
===================================================================
--- inc/libs/twig/ParserInterface.php	(revision 991)
+++ inc/libs/twig/ParserInterface.php	(revision 1101)
@@ -13,6 +13,7 @@
  * Interface implemented by parser classes.
  *
- * @package twig
- * @author  Fabien Potencier <fabien@symfony.com>
+ * @package    twig
+ * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 interface Twig_ParserInterface
Index: inc/libs/twig/SimpleFilter.php
===================================================================
--- inc/libs/twig/SimpleFilter.php	(revision 1101)
+++ inc/libs/twig/SimpleFilter.php	(revision 1101)
@@ -0,0 +1,97 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2009-2012 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a template filter.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fabien@symfony.com>
+ */
+class Twig_SimpleFilter
+{
+    protected $name;
+    protected $callable;
+    protected $options;
+    protected $arguments = array();
+
+    public function __construct($name, $callable, array $options = array())
+    {
+        $this->name = $name;
+        $this->callable = $callable;
+        $this->options = array_merge(array(
+            'needs_environment' => false,
+            'needs_context'     => false,
+            'is_safe'           => null,
+            'is_safe_callback'  => null,
+            'pre_escape'        => null,
+            'preserves_safety'  => null,
+            'node_class'        => 'Twig_Node_Expression_Filter',
+        ), $options);
+    }
+
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    public function getCallable()
+    {
+        return $this->callable;
+    }
+
+    public function getNodeClass()
+    {
+        return $this->options['node_class'];
+    }
+
+    public function setArguments($arguments)
+    {
+        $this->arguments = $arguments;
+    }
+
+    public function getArguments()
+    {
+        return $this->arguments;
+    }
+
+    public function needsEnvironment()
+    {
+        return $this->options['needs_environment'];
+    }
+
+    public function needsContext()
+    {
+        return $this->options['needs_context'];
+    }
+
+    public function getSafe(Twig_Node $filterArgs)
+    {
+        if (null !== $this->options['is_safe']) {
+            return $this->options['is_safe'];
+        }
+
+        if (null !== $this->options['is_safe_callback']) {
+            return call_user_func($this->options['is_safe_callback'], $filterArgs);
+        }
+
+        return null;
+    }
+
+    public function getPreservesSafety()
+    {
+        return $this->options['preserves_safety'];
+    }
+
+    public function getPreEscape()
+    {
+        return $this->options['pre_escape'];
+    }
+}
Index: inc/libs/twig/SimpleFunction.php
===================================================================
--- inc/libs/twig/SimpleFunction.php	(revision 1101)
+++ inc/libs/twig/SimpleFunction.php	(revision 1101)
@@ -0,0 +1,85 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2010-2012 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a template function.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fabien@symfony.com>
+ */
+class Twig_SimpleFunction
+{
+    protected $name;
+    protected $callable;
+    protected $options;
+    protected $arguments = array();
+
+    public function __construct($name, $callable, array $options = array())
+    {
+        $this->name = $name;
+        $this->callable = $callable;
+        $this->options = array_merge(array(
+            'needs_environment' => false,
+            'needs_context'     => false,
+            'is_safe'           => null,
+            'is_safe_callback'  => null,
+            'node_class'        => 'Twig_Node_Expression_Function',
+        ), $options);
+    }
+
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    public function getCallable()
+    {
+        return $this->callable;
+    }
+
+    public function getNodeClass()
+    {
+        return $this->options['node_class'];
+    }
+
+    public function setArguments($arguments)
+    {
+        $this->arguments = $arguments;
+    }
+
+    public function getArguments()
+    {
+        return $this->arguments;
+    }
+
+    public function needsEnvironment()
+    {
+        return $this->options['needs_environment'];
+    }
+
+    public function needsContext()
+    {
+        return $this->options['needs_context'];
+    }
+
+    public function getSafe(Twig_Node $functionArgs)
+    {
+        if (null !== $this->options['is_safe']) {
+            return $this->options['is_safe'];
+        }
+
+        if (null !== $this->options['is_safe_callback']) {
+            return call_user_func($this->options['is_safe_callback'], $functionArgs);
+        }
+
+        return array();
+    }
+}
Index: inc/libs/twig/SimpleTest.php
===================================================================
--- inc/libs/twig/SimpleTest.php	(revision 1101)
+++ inc/libs/twig/SimpleTest.php	(revision 1101)
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2010-2012 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a template test.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fabien@symfony.com>
+ */
+class Twig_SimpleTest
+{
+    protected $name;
+    protected $callable;
+    protected $options;
+
+    public function __construct($name, $callable, array $options = array())
+    {
+        $this->name = $name;
+        $this->callable = $callable;
+        $this->options = array_merge(array(
+            'node_class' => 'Twig_Node_Expression_Test',
+        ), $options);
+    }
+
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    public function getCallable()
+    {
+        return $this->callable;
+    }
+
+    public function getNodeClass()
+    {
+        return $this->options['node_class'];
+    }
+}
Index: inc/libs/twig/TemplateInterface.php
===================================================================
--- inc/libs/twig/TemplateInterface.php	(revision 991)
+++ inc/libs/twig/TemplateInterface.php	(revision 1101)
@@ -13,6 +13,7 @@
  * Interface implemented by all compiled templates.
  *
- * @package twig
- * @author  Fabien Potencier <fabien@symfony.com>
+ * @package    twig
+ * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 interface Twig_TemplateInterface
Index: inc/libs/twig/Test.php
===================================================================
--- inc/libs/twig/Test.php	(revision 1101)
+++ inc/libs/twig/Test.php	(revision 1101)
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2012 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a template test.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
+ */
+abstract class Twig_Test implements Twig_TestInterface, Twig_TestCallableInterface
+{
+    protected $options;
+    protected $arguments = array();
+
+    public function __construct(array $options = array())
+    {
+        $this->options = array_merge(array(
+            'callable' => null,
+        ), $options);
+    }
+
+    public function getCallable()
+    {
+        return $this->options['callable'];
+    }
+}
Index: inc/libs/twig/Test/Function.php
===================================================================
--- inc/libs/twig/Test/Function.php	(revision 991)
+++ inc/libs/twig/Test/Function.php	(revision 1101)
@@ -15,11 +15,16 @@
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
-class Twig_Test_Function implements Twig_TestInterface
+class Twig_Test_Function extends Twig_Test
 {
     protected $function;
 
-    public function __construct($function)
+    public function __construct($function, array $options = array())
     {
+        $options['callable'] = $function;
+
+        parent::__construct($options);
+
         $this->function = $function;
     }
Index: inc/libs/twig/Test/Method.php
===================================================================
--- inc/libs/twig/Test/Method.php	(revision 991)
+++ inc/libs/twig/Test/Method.php	(revision 1101)
@@ -15,12 +15,17 @@
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
-class Twig_Test_Method implements Twig_TestInterface
+class Twig_Test_Method extends Twig_Test
 {
     protected $extension;
     protected $method;
 
-    public function __construct(Twig_ExtensionInterface $extension, $method)
+    public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
     {
+        $options['callable'] = array($extension, $method);
+
+        parent::__construct($options);
+
         $this->extension = $extension;
         $this->method = $method;
Index: inc/libs/twig/Test/Node.php
===================================================================
--- inc/libs/twig/Test/Node.php	(revision 991)
+++ inc/libs/twig/Test/Node.php	(revision 1101)
@@ -15,11 +15,14 @@
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
-class Twig_Test_Node implements Twig_TestInterface
+class Twig_Test_Node extends Twig_Test
 {
     protected $class;
 
-    public function __construct($class)
+    public function __construct($class, array $options = array())
     {
+        parent::__construct($options);
+
         $this->class = $class;
     }
Index: inc/libs/twig/TestCallableInterface.php
===================================================================
--- inc/libs/twig/TestCallableInterface.php	(revision 1101)
+++ inc/libs/twig/TestCallableInterface.php	(revision 1101)
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2012 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Represents a callable template test.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
+ */
+interface Twig_TestCallableInterface
+{
+    public function getCallable();
+}
Index: inc/libs/twig/TestInterface.php
===================================================================
--- inc/libs/twig/TestInterface.php	(revision 991)
+++ inc/libs/twig/TestInterface.php	(revision 1101)
@@ -15,4 +15,5 @@
  * @package    twig
  * @author     Fabien Potencier <fabien@symfony.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 interface Twig_TestInterface
Index: inc/libs/twig/TokenParser/For.php
===================================================================
--- inc/libs/twig/TokenParser/For.php	(revision 991)
+++ inc/libs/twig/TokenParser/For.php	(revision 1101)
@@ -34,23 +34,24 @@
     {
         $lineno = $token->getLine();
+        $stream = $this->parser->getStream();
         $targets = $this->parser->getExpressionParser()->parseAssignmentExpression();
-        $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, 'in');
+        $stream->expect(Twig_Token::OPERATOR_TYPE, 'in');
         $seq = $this->parser->getExpressionParser()->parseExpression();
 
         $ifexpr = null;
-        if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'if')) {
-            $this->parser->getStream()->next();
+        if ($stream->test(Twig_Token::NAME_TYPE, 'if')) {
+            $stream->next();
             $ifexpr = $this->parser->getExpressionParser()->parseExpression();
         }
 
-        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+        $stream->expect(Twig_Token::BLOCK_END_TYPE);
         $body = $this->parser->subparse(array($this, 'decideForFork'));
-        if ($this->parser->getStream()->next()->getValue() == 'else') {
-            $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+        if ($stream->next()->getValue() == 'else') {
+            $stream->expect(Twig_Token::BLOCK_END_TYPE);
             $else = $this->parser->subparse(array($this, 'decideForEnd'), true);
         } else {
             $else = null;
         }
-        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+        $stream->expect(Twig_Token::BLOCK_END_TYPE);
 
         if (count($targets) > 1) {
@@ -63,4 +64,9 @@
             $valueTarget = $targets->getNode(0);
             $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine());
+        }
+
+        if ($ifexpr) {
+            $this->checkLoopUsageCondition($stream, $ifexpr);
+            $this->checkLoopUsageBody($stream, $body);
         }
 
@@ -78,4 +84,45 @@
     }
 
+    // the loop variable cannot be used in the condition
+    protected function checkLoopUsageCondition(Twig_TokenStream $stream, Twig_NodeInterface $node)
+    {
+        if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
+            throw new Twig_Error_Syntax('The "loop" variable cannot be used in a looping condition', $node->getLine(), $stream->getFilename());
+        }
+
+        foreach ($node as $n) {
+            if (!$n) {
+                continue;
+            }
+
+            $this->checkLoopUsageCondition($stream, $n);
+        }
+    }
+
+    // check usage of non-defined loop-items
+    // it does not catch all problems (for instance when a for is included into another or when the variable is used in an include)
+    protected function checkLoopUsageBody(Twig_TokenStream $stream, Twig_NodeInterface $node)
+    {
+        if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
+            $attribute = $node->getNode('attribute');
+            if ($attribute instanceof Twig_Node_Expression_Constant && in_array($attribute->getAttribute('value'), array('length', 'revindex0', 'revindex', 'last'))) {
+                throw new Twig_Error_Syntax(sprintf('The "loop.%s" variable is not defined when looping with a condition', $attribute->getAttribute('value')), $node->getLine(), $stream->getFilename());
+            }
+        }
+
+        // should check for parent.loop.XXX usage
+        if ($node instanceof Twig_Node_For) {
+            return;
+        }
+
+        foreach ($node as $n) {
+            if (!$n) {
+                continue;
+            }
+
+            $this->checkLoopUsageBody($stream, $n);
+        }
+    }
+
     /**
      * Gets the tag name associated with this token parser.
Index: inc/libs/twig/TokenParser/Macro.php
===================================================================
--- inc/libs/twig/TokenParser/Macro.php	(revision 991)
+++ inc/libs/twig/TokenParser/Macro.php	(revision 1101)
@@ -34,5 +34,5 @@
         $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
 
-        $arguments = $this->parser->getExpressionParser()->parseArguments();
+        $arguments = $this->parser->getExpressionParser()->parseArguments(true, true);
 
         $stream->expect(Twig_Token::BLOCK_END_TYPE);
Index: inc/libs/twig/TokenParserBroker.php
===================================================================
--- inc/libs/twig/TokenParserBroker.php	(revision 991)
+++ inc/libs/twig/TokenParserBroker.php	(revision 1101)
@@ -14,6 +14,7 @@
  * Default implementation of a token parser broker.
  *
- * @package twig
- * @author  Arnaud Le Blanc <arnaud.lb@gmail.com>
+ * @package    twig
+ * @author     Arnaud Le Blanc <arnaud.lb@gmail.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface
@@ -56,4 +57,17 @@
 
     /**
+     * Removes a TokenParser.
+     *
+     * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance
+     */
+    public function removeTokenParser(Twig_TokenParserInterface $parser)
+    {
+        $name = $parser->getTag();
+        if (isset($this->parsers[$name]) && $parser === $this->parsers[$name]) {
+            unset($this->parsers[$name]);
+        }
+    }
+
+    /**
      * Adds a TokenParserBroker.
      *
@@ -63,4 +77,16 @@
     {
         $this->brokers[] = $broker;
+    }
+
+    /**
+     * Removes a TokenParserBroker.
+     *
+     * @param Twig_TokenParserBroker $broker A Twig_TokenParserBroker instance
+     */
+    public function removeTokenParserBroker(Twig_TokenParserBroker $broker)
+    {
+        if (false !== $pos = array_search($broker, $this->brokers)) {
+            unset($this->brokers[$pos]);
+        }
     }
 
Index: inc/libs/twig/TokenParserBrokerInterface.php
===================================================================
--- inc/libs/twig/TokenParserBrokerInterface.php	(revision 991)
+++ inc/libs/twig/TokenParserBrokerInterface.php	(revision 1101)
@@ -16,6 +16,7 @@
  * Token parser brokers allows to implement custom logic in the process of resolving a token parser for a given tag name.
  *
- * @package twig
- * @author  Arnaud Le Blanc <arnaud.lb@gmail.com>
+ * @package    twig
+ * @author     Arnaud Le Blanc <arnaud.lb@gmail.com>
+ * @deprecated since 1.12 (to be removed in 2.0)
  */
 interface Twig_TokenParserBrokerInterface
Index: inc/libs/twig/TokenStream.php
===================================================================
--- inc/libs/twig/TokenStream.php	(revision 991)
+++ inc/libs/twig/TokenStream.php	(revision 1101)
@@ -59,5 +59,5 @@
     {
         if (!isset($this->tokens[++$this->current])) {
-            throw new Twig_Error_Syntax('Unexpected end of template', $this->token[$this->current - 1]->getLine(), $this->filename);
+            throw new Twig_Error_Syntax('Unexpected end of template', $this->tokens[$this->current - 1]->getLine(), $this->filename);
         }
 
@@ -98,5 +98,5 @@
     {
         if (!isset($this->tokens[$this->current + $number])) {
-            throw new Twig_Error_Syntax('Unexpected end of template', $this->token[$this->current + $number - 1]->getLine(), $this->filename);
+            throw new Twig_Error_Syntax('Unexpected end of template', $this->tokens[$this->current + $number - 1]->getLine(), $this->filename);
         }
 
