1b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)# -*- coding: utf-8 -*- 2b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)""" 3b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) jinja2.optimizer 4b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ~~~~~~~~~~~~~~~~ 5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 6b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) The jinja optimizer is currently trying to constant fold a few expressions 7b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) and modify the AST in place so that it should be easier to evaluate it. 8b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 9b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Because the AST does not contain all the scoping information and the 10b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) compiler has to find that out, we cannot do all the optimizations we 11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) want. For example loop unrolling doesn't work because unrolled loops would 12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) have a different scoping. 13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 14b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) The solution would be a second syntax tree that has the scoping rules stored. 15b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) :copyright: (c) 2010 by the Jinja Team. 17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) :license: BSD. 18b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)""" 19b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from jinja2 import nodes 20b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from jinja2.visitor import NodeTransformer 21b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 22b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 23b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)def optimize(node, environment): 24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """The context hint can be used to perform an static optimization 25b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) based on the context given.""" 26b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) optimizer = Optimizer(environment) 27b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return optimizer.visit(node) 28b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 29b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class Optimizer(NodeTransformer): 31b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def __init__(self, environment): 33b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.environment = environment 34b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 35b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def visit_If(self, node): 36b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Eliminate dead code.""" 37b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # do not optimize ifs that have a block inside so that it doesn't 38b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # break super(). 39b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if node.find(nodes.Block) is not None: 40b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return self.generic_visit(node) 41b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) try: 42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) val = self.visit(node.test).as_const() 43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) except nodes.Impossible: 44b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return self.generic_visit(node) 45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if val: 46b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) body = node.body 47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) else: 48b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) body = node.else_ 49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) result = [] 50b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for node in body: 51b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) result.extend(self.visit_list(node)) 52b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return result 53b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def fold(self, node): 55b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) """Do constant folding.""" 56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) node = self.generic_visit(node) 57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) try: 58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return nodes.Const.from_untrusted(node.as_const(), 59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) lineno=node.lineno, 60b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) environment=self.environment) 61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) except nodes.Impossible: 62b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return node 63b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) visit_Add = visit_Sub = visit_Mul = visit_Div = visit_FloorDiv = \ 65b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) visit_Pow = visit_Mod = visit_And = visit_Or = visit_Pos = visit_Neg = \ 66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) visit_Not = visit_Compare = visit_Getitem = visit_Getattr = visit_Call = \ 67b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) visit_Filter = visit_Test = visit_CondExpr = fold 68b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) del fold 69