some more stuff for jinja2

--HG--
branch : trunk
diff --git a/bench.py b/bench.py
index 1ead1ec..0e6b307 100644
--- a/bench.py
+++ b/bench.py
@@ -1,19 +1,127 @@
-from jinja import Environment as E1
-from jinja2 import Environment as E2
-from mako.template import Template as M
+from django.conf import settings
+settings.configure()
+from django.template import Template as DjangoTemplate, Context as DjangoContext
+from jinja2 import Environment as JinjaEnvironment
+from mako.template import Template as MakoTemplate
+from timeit import Timer
 
-t1, t2 = [e.from_string("""
-<ul>
-{%- for item in seq %}
-    <li>{{ item|e }}</li>
-{%- endfor %}
-</ul>
-""") for e in E1(), E2()]
 
-m = M("""
-<ul>
-% for item in seq:
-    <li>${item|h}</li>
-% endfor
-</ul>
+jinja_template = JinjaEnvironment(
+    line_statement_prefix='%',
+    variable_start_string="${",
+    variable_end_string="}"
+).from_string("""\
+<!doctype html>
+<html>
+  <head>
+    <title>${page_title|e}
+  </head>
+  <body>
+    <div class="header">
+      <h1>${page_title|e}</h1>
+    </div>
+    <ul class="navigation">
+    % for href, caption in [
+        ('index.html', 'Index'),
+        ('downloads.html', 'Downloads'),
+        ('products.html', 'Products')
+      ]
+      <li><a href="${href|e}">${caption|e}</a></li>
+    % endfor
+    </ul>
+    <div class="table">
+      <table>
+      % for row in table
+        <tr>
+        % for cell in row
+          <td>${cell}</td>
+        % endfor
+        </tr>
+      % endfor
+      </table>
+    </div>
+  </body>
+</html>\
 """)
+
+django_template = DjangoTemplate("""\
+<!doctype html>
+<html>
+  <head>
+    <title>{{ page_title }}
+  </head>
+  <body>
+    <div class="header">
+      <h1>{{ page_title }}</h1>
+    </div>
+    <ul class="navigation">
+    {% for href, caption in navigation %}
+      <li><a href="{{ href }}">{{ caption }}</a></li>
+    {% endfor %}
+    </ul>
+    <div class="table">
+      <table>
+      {% for row in table %}
+        <tr>
+        {% for cell in row %}
+          <td>{{ cell }}</td>
+        {% endfor %}
+        </tr>
+      {% endfor %}
+      </table>
+    </div>
+  </body>
+</html>\
+""")
+
+mako_template = MakoTemplate("""\
+<!doctype html>
+<html>
+  <head>
+    <title>${page_title|h}
+  </head>
+  <body>
+    <div class="header">
+      <h1>${page_title|h}</h1>
+    </div>
+    <ul class="navigation">
+    % for href, caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]:
+      <li><a href="${href|h}">${caption|h}</a></li>
+    % endfor
+    </ul>
+    <div class="table">
+      <table>
+      % for row in table:
+        <tr>
+        % for cell in row:
+          <td>${cell}</td>
+        % endfor
+        </tr>
+      % endfor
+      </table>
+    </div>
+  </body>
+</html>\
+""")
+
+context = {
+    'page_title': 'mitsuhiko\'s benchmark',
+    'table': [dict(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9,j=10) for x in range(1000)]
+}
+
+def test_jinja():
+    jinja_template.render(context)
+
+def test_django():
+    c = DjangoContext(context)
+    c['navigation'] = [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]
+    django_template.render(c)
+
+def test_mako():
+    mako_template.render(**context)
+
+
+for test in 'jinja', 'mako', 'django':
+    t = Timer(setup='from __main__ import test_%s as bench' % test,
+              stmt='bench()')
+    print '%-20s%.4fms' % (test, t.timeit(number=20) / 20)
diff --git a/jinja2/compiler.py b/jinja2/compiler.py
index e291f1d..e692184 100644
--- a/jinja2/compiler.py
+++ b/jinja2/compiler.py
@@ -564,9 +564,9 @@
         for arg in node.defaults:
             self.visit(arg)
             self.write(', ')
-        self.write('), %r, %r)' % (
-            macro_frame.accesses_arguments,
-            macro_frame.accesses_caller
+        self.write('), %s, %s)' % (
+            macro_frame.accesses_arguments and '1' or '0',
+            macro_frame.accesses_caller and '1' or '0'
         ))
 
     def visit_CallBlock(self, node, frame):
@@ -581,7 +581,7 @@
         for arg in node.defaults:
             self.visit(arg)
             self.write(', ')
-        self.write('), %r, False)' % call_frame.accesses_arguments)
+        self.write('), %s, 0)' % (call_frame.accesses_arguments and '1' or '0'))
         if frame.buffer is None:
             self.writeline('yield ', node)
         else:
diff --git a/jinja2/environment.py b/jinja2/environment.py
index fb8101b..8458a23 100644
--- a/jinja2/environment.py
+++ b/jinja2/environment.py
@@ -107,7 +107,6 @@
             source = self.parse(source, filename)
         node = optimize(source, self)
         source = generate(node, self, filename)
-        print source
         if raw:
             return source
         if isinstance(filename, unicode):
diff --git a/jinja2/nodes.py b/jinja2/nodes.py
index 3b0ac3c..e1857d2 100644
--- a/jinja2/nodes.py
+++ b/jinja2/nodes.py
@@ -389,13 +389,14 @@
     """{{ foo|bar|baz }}"""
     fields = ('node', 'name', 'args', 'kwargs', 'dyn_args', 'dyn_kwargs')
 
-    def as_const(self):
-        if self.node is None:
+    def as_const(self, obj=None):
+        if self.node is obj is None:
             raise Impossible()
         filter = self.environment.filters.get(self.name)
         if filter is None or getattr(filter, 'contextfilter', False):
             raise nodes.Impossible()
-        obj = self.node.as_const()
+        if obj is None:
+            obj = self.node.as_const()
         args = [x.as_const() for x in self.args]
         kwargs = dict(x.as_const() for x in self.kwargs)
         if self.dyn_args is not None:
diff --git a/jinja2/optimizer.py b/jinja2/optimizer.py
index bd97fa0..d2550f4 100644
--- a/jinja2/optimizer.py
+++ b/jinja2/optimizer.py
@@ -95,6 +95,32 @@
         finally:
             context.pop()
 
+    def visit_FilterBlock(self, node, context):
+        """Try to filter a block at compile time."""
+        node = self.generic_visit(node, context)
+        context.push()
+
+        # check if we can evaluate the wrapper body into a string
+        # at compile time
+        buffer = []
+        for child in node.body:
+            if not isinstance(child, nodes.Output):
+                return node
+            for item in child.optimized_nodes():
+                if isinstance(item, nodes.Node):
+                    return node
+                buffer.append(item)
+
+        # now check if we can evaluate the filter at compile time.
+        try:
+            data = node.filter.as_const(u''.join(buffer))
+        except nodes.Impossible:
+            return node
+
+        context.pop()
+        const = nodes.Const(data, lineno=node.lineno)
+        return nodes.Output([const], lineno=node.lineno)
+
     def visit_For(self, node, context):
         """Loop unrolling for iterable constant values."""
         try:
diff --git a/test_filter_and_linestatements.py b/test_filter_and_linestatements.py
index e5d94d0..c9e8f95 100644
--- a/test_filter_and_linestatements.py
+++ b/test_filter_and_linestatements.py
@@ -16,6 +16,9 @@
 % endcall
 % filter escape
     <hello world>
+    % for item in [1, 2, 3]
+      -  ${item}
+    % endfor
 % endfilter
 """)