1# -*- coding: utf-8 -*- 2""" 3 jinja2.optimizer 4 ~~~~~~~~~~~~~~~~ 5 6 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. 8 9 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. 13 14 The solution would be a second syntax tree that has the scoping rules stored. 15 16 :copyright: (c) 2010 by the Jinja Team. 17 :license: BSD. 18""" 19from jinja2 import nodes 20from jinja2.visitor import NodeTransformer 21 22 23def optimize(node, environment): 24 """The context hint can be used to perform an static optimization 25 based on the context given.""" 26 optimizer = Optimizer(environment) 27 return optimizer.visit(node) 28 29 30class Optimizer(NodeTransformer): 31 32 def __init__(self, environment): 33 self.environment = environment 34 35 def visit_If(self, node): 36 """Eliminate dead code.""" 37 # 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) 41 try: 42 val = self.visit(node.test).as_const() 43 except nodes.Impossible: 44 return self.generic_visit(node) 45 if val: 46 body = node.body 47 else: 48 body = node.else_ 49 result = [] 50 for node in body: 51 result.extend(self.visit_list(node)) 52 return result 53 54 def fold(self, node): 55 """Do constant folding.""" 56 node = self.generic_visit(node) 57 try: 58 return nodes.Const.from_untrusted(node.as_const(), 59 lineno=node.lineno, 60 environment=self.environment) 61 except nodes.Impossible: 62 return node 63 64 visit_Add = visit_Sub = visit_Mul = visit_Div = visit_FloorDiv = \ 65 visit_Pow = visit_Mod = visit_And = visit_Or = visit_Pos = visit_Neg = \ 66 visit_Not = visit_Compare = visit_Getitem = visit_Getattr = visit_Call = \ 67 visit_Filter = visit_Test = visit_CondExpr = fold 68 del fold 69