Index: third_party/jinja2/optimizer.py |
diff --git a/third_party/jinja2/optimizer.py b/third_party/jinja2/optimizer.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..00eab115e1c19a86bb1ec64b7cf626fbf413e126 |
--- /dev/null |
+++ b/third_party/jinja2/optimizer.py |
@@ -0,0 +1,68 @@ |
+# -*- coding: utf-8 -*- |
+""" |
+ jinja2.optimizer |
+ ~~~~~~~~~~~~~~~~ |
+ |
+ The jinja optimizer is currently trying to constant fold a few expressions |
+ and modify the AST in place so that it should be easier to evaluate it. |
+ |
+ Because the AST does not contain all the scoping information and the |
+ compiler has to find that out, we cannot do all the optimizations we |
+ want. For example loop unrolling doesn't work because unrolled loops would |
+ have a different scoping. |
+ |
+ The solution would be a second syntax tree that has the scoping rules stored. |
+ |
+ :copyright: (c) 2010 by the Jinja Team. |
+ :license: BSD. |
+""" |
+from jinja2 import nodes |
+from jinja2.visitor import NodeTransformer |
+ |
+ |
+def optimize(node, environment): |
+ """The context hint can be used to perform an static optimization |
+ based on the context given.""" |
+ optimizer = Optimizer(environment) |
+ return optimizer.visit(node) |
+ |
+ |
+class Optimizer(NodeTransformer): |
+ |
+ def __init__(self, environment): |
+ self.environment = environment |
+ |
+ def visit_If(self, node): |
+ """Eliminate dead code.""" |
+ # do not optimize ifs that have a block inside so that it doesn't |
+ # break super(). |
+ if node.find(nodes.Block) is not None: |
+ return self.generic_visit(node) |
+ try: |
+ val = self.visit(node.test).as_const() |
+ except nodes.Impossible: |
+ return self.generic_visit(node) |
+ if val: |
+ body = node.body |
+ else: |
+ body = node.else_ |
+ result = [] |
+ for node in body: |
+ result.extend(self.visit_list(node)) |
+ return result |
+ |
+ def fold(self, node): |
+ """Do constant folding.""" |
+ node = self.generic_visit(node) |
+ try: |
+ return nodes.Const.from_untrusted(node.as_const(), |
+ lineno=node.lineno, |
+ environment=self.environment) |
+ except nodes.Impossible: |
+ return node |
+ |
+ visit_Add = visit_Sub = visit_Mul = visit_Div = visit_FloorDiv = \ |
+ visit_Pow = visit_Mod = visit_And = visit_Or = visit_Pos = visit_Neg = \ |
+ visit_Not = visit_Compare = visit_Getitem = visit_Getattr = visit_Call = \ |
+ visit_Filter = visit_Test = visit_CondExpr = fold |
+ del fold |