blob: 8f92e38952a6ff4e8f271927b0509ddcd87c1c56 [file] [log] [blame]
Christoph Hack9d99e472008-04-08 20:21:11 +02001# -*- coding: utf-8 -*-
2"""
3 jinja2.optimizer
4 ~~~~~~~~~~~~~~~~
5
Armin Ronacher07a21ba2008-04-23 22:28:42 +02006 The jinja optimizer is currently trying to constant fold a few expressions
7 and modify the AST in place so that it should be easier to evaluate it.
Christoph Hack9d99e472008-04-08 20:21:11 +02008
Armin Ronacher07a21ba2008-04-23 22:28:42 +02009 Because the AST does not contain all the scoping information and the
10 compiler has to find that out, we cannot do all the optimizations we
11 want. For example loop unrolling doesn't work because unrolled loops would
12 have a different scoping.
Christoph Hack9d99e472008-04-08 20:21:11 +020013
Armin Ronacher07a21ba2008-04-23 22:28:42 +020014 The solution would be a second syntax tree that has the scoping rules stored.
Christoph Hack9d99e472008-04-08 20:21:11 +020015
Armin Ronacher2e9396b2008-04-16 14:21:57 +020016 :copyright: Copyright 2008 by Christoph Hack, Armin Ronacher.
Christoph Hack9d99e472008-04-08 20:21:11 +020017 :license: GNU GPL.
18"""
Christoph Hack9d99e472008-04-08 20:21:11 +020019from jinja2 import nodes
Armin Ronacher981cbf62008-05-13 09:12:27 +020020from jinja2.visitor import NodeTransformer
Christoph Hack9d99e472008-04-08 20:21:11 +020021
22
Armin Ronacher981cbf62008-05-13 09:12:27 +020023def optimize(node, environment):
Armin Ronacherbcb7c532008-04-11 16:30:34 +020024 """The context hint can be used to perform an static optimization
25 based on the context given."""
26 optimizer = Optimizer(environment)
Armin Ronacher981cbf62008-05-13 09:12:27 +020027 return optimizer.visit(node)
Armin Ronacher81b88172008-04-09 00:40:05 +020028
29
Christoph Hackb40b8802008-04-08 23:01:58 +020030class Optimizer(NodeTransformer):
Christoph Hack9d99e472008-04-08 20:21:11 +020031
Armin Ronacher81b88172008-04-09 00:40:05 +020032 def __init__(self, environment):
Christoph Hack9d99e472008-04-08 20:21:11 +020033 self.environment = environment
Christoph Hack9d99e472008-04-08 20:21:11 +020034
Armin Ronacher981cbf62008-05-13 09:12:27 +020035 def visit_If(self, node):
36 """Eliminate dead code."""
Armin Ronacher6df604e2008-05-23 22:18:38 +020037 # do not optimize ifs that have a block inside so that it doesn't
38 # break super().
39 if node.find(nodes.Block) is not None:
40 return self.generic_visit(node)
Armin Ronacherc9705c22008-04-27 21:28:03 +020041 try:
Armin Ronacher981cbf62008-05-13 09:12:27 +020042 val = self.visit(node.test).as_const()
Armin Ronacher81b88172008-04-09 00:40:05 +020043 except nodes.Impossible:
Armin Ronacher981cbf62008-05-13 09:12:27 +020044 return self.generic_visit(node)
Armin Ronacher81b88172008-04-09 00:40:05 +020045 if val:
Armin Ronacherc9705c22008-04-27 21:28:03 +020046 body = node.body
47 else:
48 body = node.else_
49 result = []
50 for node in body:
Armin Ronacher981cbf62008-05-13 09:12:27 +020051 result.extend(self.visit_list(node))
Armin Ronacherc9705c22008-04-27 21:28:03 +020052 return result
Armin Ronacher81b88172008-04-09 00:40:05 +020053
Armin Ronacher981cbf62008-05-13 09:12:27 +020054 def fold(self, node):
Armin Ronacher180a1bd2008-04-09 12:14:24 +020055 """Do constant folding."""
Armin Ronacher981cbf62008-05-13 09:12:27 +020056 node = self.generic_visit(node)
Armin Ronacher180a1bd2008-04-09 12:14:24 +020057 try:
Armin Ronacher4dfc9752008-04-09 15:03:29 +020058 return nodes.Const.from_untrusted(node.as_const(),
Armin Ronacherd55ab532008-04-09 16:13:39 +020059 lineno=node.lineno,
60 environment=self.environment)
Armin Ronacher180a1bd2008-04-09 12:14:24 +020061 except nodes.Impossible:
62 return node
Armin Ronacherfed44b52008-04-13 19:42:53 +020063
Armin Ronacher180a1bd2008-04-09 12:14:24 +020064 visit_Add = visit_Sub = visit_Mul = visit_Div = visit_FloorDiv = \
65 visit_Pow = visit_Mod = visit_And = visit_Or = visit_Pos = visit_Neg = \
Armin Ronacherd55ab532008-04-09 16:13:39 +020066 visit_Not = visit_Compare = visit_Subscript = visit_Call = \
Armin Ronacherfed44b52008-04-13 19:42:53 +020067 visit_Filter = visit_Test = visit_CondExpr = fold
Armin Ronacher4dfc9752008-04-09 15:03:29 +020068 del fold