added optimizer
authorChristoph Hack <christoph@tux21b.org>
Tue, 8 Apr 2008 18:21:11 +0000 (20:21 +0200)
committerChristoph Hack <christoph@tux21b.org>
Tue, 8 Apr 2008 18:21:11 +0000 (20:21 +0200)
--HG--
branch : trunk

1  2 
jinja2/compiler.py
jinja2/optimizer.py
test_optimizer.py

index c26c1b295808eb4d2aa2fb73e1e7acae9877ba8c,bdf195f1a221cfdd478443100598e4b0b7f2829b..f173685063e0fb3efed2c80f120fc8d0146f1bad
@@@ -564,22 -551,10 +566,13 @@@ class CodeGenerator(NodeVisitor)
              self.visit(node.step, frame)
  
      def visit_Filter(self, node, frame):
-         value = node.node
-         flen = len(node.filters)
-         if isinstance(value, nodes.Const):
-             # try to optimize filters on constant values
-             for filter in reversed(node.filters):
-                 value = nodes.Const(self.environment.filters \
-                     .get(filter.name)(self.environment, value.value))
-                 print value
-                 flen -= 1
-         for filter in node.filters[:flen]:
+         for filter in node.filters:
 -            self.write('context.filters[%r](' % filter.name)
 +            if filter.name in frame.identifiers.declared_filter:
 +                self.write('f_%s(' % filter.name)
 +            else:
 +                self.write('context.filter[%r](' % filter.name)
-         self.visit(value, frame)
-         for filter in reversed(node.filters[:flen]):
+         self.visit(node.node, frame)
+         for filter in reversed(node.filters):
              self.signature(filter, frame)
              self.write(')')
  
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8793a88a91bd71fe0f6cf468a4ae7468de02d380
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,62 @@@
++# -*- coding: utf-8 -*-
++"""
++    jinja2.optimizer
++    ~~~~~~~~~~~~~~~~
++
++    This module tries to optimize template trees by:
++
++        * eliminating constant nodes
++        * evaluating filters and macros on constant nodes
++        * unroll loops on constant values
++        * replace variables which are already known (because the doesn't
++          change often and you want to prerender a template) with constants
++
++    After the optimation you will get a new, simplier template which can
++    be saved again for later rendering. But even if you don't want to
++    prerender a template, this module might speed up your templates a bit
++    if you are using a lot of constants.
++
++    :copyright: Copyright 2008 by Christoph Hack.
++    :license: GNU GPL.
++"""
++from copy import copy
++from random import randrange
++from operator import xor
++from cStringIO import StringIO
++from jinja2 import nodes
++from jinja2.visitor import NodeVisitor, NodeTransformer
++from jinja2.exceptions import TemplateAssertionError
++
++
++class Optimizer(NodeVisitor):
++
++    def __init__(self, environment, context={}):
++        self.environment = environment
++        self.context = context
++
++    def visit_Output(self, node):
++        node.nodes = [self.visit(n) for n in node.nodes]
++        return node
++
++    def visit_Filter(self, node):
++        """Try to evaluate filters if possible."""
++        value = self.visit(node.node)
++        if isinstance(value, nodes.Const):
++            x = value.value
++            for filter in reversed(node.filters):
++                # XXX: call filters with arguments
++                x = self.environment.filters[filter.name](self.environment, x)
++                # XXX: don't optimize context dependent filters
++            return nodes.Const(x)
++        return node
++
++    def generic_visit(self, node, *args, **kwargs):
++        NodeVisitor.generic_visit(self, node, *args, **kwargs)
++        return node
++
++
++def optimize(ast, env, clone=True):
++    optimizer = Optimizer(env)
++    if clone:
++        ast = copy(ast)
++    return optimizer.visit(ast)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d63277787ec50d765b40a4af444b0029c5f79bd4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,18 @@@
++from jinja2 import Environment
++from jinja2.compiler import generate
++from jinja2.optimizer import optimize
++
++
++env = Environment()
++ast = env.parse("""
++    Hi {{ "<blub>"|e }},
++    how are you?
++""")
++print ast
++print
++print generate(ast, env, "foo.html")
++print
++ast = optimize(ast, env)
++print ast
++print
++print generate(ast, env, "foo.html")