summaryrefslogtreecommitdiff
path: root/astroid/rebuilder.py
diff options
context:
space:
mode:
authorClaudiu Popa <cpopa@cloudbasesolutions.com>2015-01-18 21:59:52 +0200
committerClaudiu Popa <cpopa@cloudbasesolutions.com>2015-01-18 21:59:52 +0200
commit7c2ac2346f47654f6827f186ee4140ccf1f82be1 (patch)
tree750d0e86d1ffd884319c5b10f95e69ae34f3e39b /astroid/rebuilder.py
parent0cec71861ed47d9fa546792dc6142501fdb71ace (diff)
downloadastroid-7c2ac2346f47654f6827f186ee4140ccf1f82be1.tar.gz
Add the ability to optimize small ast subtrees.
The first use of the AST peephole optimizer is the optimization of multiple BinOp nodes. This removes recursivity in the rebuilder when dealing with a lot of small strings joined by the addition operator. which are now precomputed to the final string. Closes issue #59.
Diffstat (limited to 'astroid/rebuilder.py')
-rw-r--r--astroid/rebuilder.py22
1 files changed, 21 insertions, 1 deletions
diff --git a/astroid/rebuilder.py b/astroid/rebuilder.py
index 14c606e..c83c869 100644
--- a/astroid/rebuilder.py
+++ b/astroid/rebuilder.py
@@ -23,7 +23,7 @@ import sys
from _ast import (
Expr as Discard, Str,
# binary operators
- Add, Div, FloorDiv, Mod, Mult, Pow, Sub, BitAnd, BitOr, BitXor,
+ Add, BinOp, Div, FloorDiv, Mod, Mult, Pow, Sub, BitAnd, BitOr, BitXor,
LShift, RShift,
# logical operators
And, Or,
@@ -34,6 +34,7 @@ from _ast import (
)
from astroid import nodes as new
+from astroid import astpeephole
_BIN_OP_CLASSES = {Add: '+',
@@ -136,6 +137,7 @@ class TreeRebuilder(object):
self._delayed_assattr = []
self._visit_meths = {}
self._transform = manager.transform
+ self._peepholer = astpeephole.ASTPeepholeOptimizer()
def visit_module(self, node, modname, modpath, package):
"""visit a Module node by returning a fresh instance of it"""
@@ -281,6 +283,24 @@ class TreeRebuilder(object):
def visit_binop(self, node, parent):
"""visit a BinOp node by returning a fresh instance of it"""
+ if isinstance(node.left, BinOp):
+ # Optimize BinOp operations in order to remove
+ # redundant recursion. For instance, if the
+ # following code is parsed in order to obtain
+ # its ast, then the rebuilder will fail with an
+ # infinite recursion, the same will happen with the
+ # inference engine as well. There's no need to hold
+ # so many objects for the BinOp if they can be reduced
+ # to something else (also, the optimization
+ # might handle only Const binops, which isn't a big
+ # problem for the correctness of the program).
+ #
+ # ("a" + "b" + # one thousand more + "c")
+ newnode = self._peepholer.optimize_binop(node)
+ if newnode:
+ _lineno_parent(node, newnode, parent)
+ return newnode
+
newnode = new.BinOp()
_lineno_parent(node, newnode, parent)
newnode.left = self.visit(node.left, newnode)