[pypy-svn] r29834 - in pypy/dist/pypy/lib: . test2

mwh at codespeak.net mwh at codespeak.net
Sat Jul 8 16:09:06 CEST 2006


Author: mwh
Date: Sat Jul  8 16:09:01 2006
New Revision: 29834

Added:
   pypy/dist/pypy/lib/optimizers.py   (contents, props changed)
   pypy/dist/pypy/lib/test2/test_optimizers.py   (contents, props changed)
Log:
(misto, mwh)
A first cut at a constant folding optimization step.
Not enabled by default (it's rather slow)
import parser, optimizers
parser.install_compiler_hook(optimizers.hook)
will enable.


Added: pypy/dist/pypy/lib/optimizers.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lib/optimizers.py	Sat Jul  8 16:09:01 2006
@@ -0,0 +1,69 @@
+import parser, operator
+
+def binaryVisit(operation):
+    def visit(self, node):
+        left = node.left
+        right = node.right
+        if isinstance(left, parser.ASTConst) and \
+               isinstance(right, parser.ASTConst):
+            if type(left.value) == type(right.value):
+                return parser.ASTConst(operation(left.value, right.value))
+        return node
+    return visit
+
+def bitopVisit(astclass, operation):
+    def compress(values):
+        while len(values) > 1:
+            values[0] = operation(values[0], values[1])
+            del values[1]
+        return values[0]
+    def visit(self, node):
+        values = []
+        for i, n in enumerate(node.nodes):
+            if not isinstance(n, parser.ASTConst):
+                if values:
+                    return astclass([compress(values)] + node.nodes[i:])
+                else:
+                    return node
+            values.append(n.value)
+        return parser.ASTConst(compress(values))
+    return visit
+        
+
+class Folder:
+    def __init__(self):
+        pass
+        
+    def defaultvisit(self, node):
+        return node
+
+    def __getattr__(self, attrname):
+        if attrname.startswith('visit'):
+            return self.defaultvisit
+        raise AttributeError(attrname)
+
+    visitAdd = binaryVisit(operator.add)
+    visitSub = binaryVisit(operator.sub)
+    visitMul = binaryVisit(operator.mul)
+    visitDiv = binaryVisit(operator.div)
+
+    visitBitand = bitopVisit(parser.ASTBitand, operator.and_)
+    visitBitor  = bitopVisit(parser.ASTBitor, operator.or_)
+    visitBitxor = bitopVisit(parser.ASTBitxor, operator.xor)
+
+    def visitTuple(self, node):
+        contents = []
+        for n in node.nodes:
+            if not isinstance(n, parser.ASTConst):
+                return node
+            contents.append(n.value)
+        return parser.ASTConst(tuple(contents))
+
+    def visitDiscard(self, node):
+        if isinstance(node, parser.ASTConst):
+            return None
+        else:
+            return node
+
+def hook(ast, enc):
+    return ast.mutate(Folder())

Added: pypy/dist/pypy/lib/test2/test_optimizers.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lib/test2/test_optimizers.py	Sat Jul  8 16:09:01 2006
@@ -0,0 +1,57 @@
+
+def expr(src):
+    from parser import source2ast
+    module = source2ast(src)
+    return module.node.nodes[0].expr
+
+class AppTestFolder:
+    def setup_class(cls):
+        cls.w_expr, cls.w_check_const_fold = cls.space.unpackiterable(cls.space.appexec([], '''():
+        from parser import source2ast, ASTConst, ASTNode
+        from optimizers import Folder
+
+        def expr(cls, src):
+            module = source2ast(src)
+            expr = module.node.nodes[0].expr
+            assert isinstance(expr, cls)
+            return expr
+
+        def check_const_fold(src, value, cls=ASTNode):
+            exprnode = expr(cls, src)
+            exprnode = exprnode.mutate(Folder())
+            assert isinstance(exprnode, ASTConst) and exprnode.value == value
+
+        return expr, check_const_fold'''))
+
+    def test_expr(self):
+        from parser import ASTConst
+        raises(AssertionError, self.expr, ASTConst, "a")
+
+    def test_bitfold(self):
+        from parser import ASTBitand, ASTBitor, ASTBitxor
+
+        self.check_const_fold('1&3', 1, ASTBitand)
+        self.check_const_fold('1|3', 3, ASTBitor)
+        self.check_const_fold('1^3', 2, ASTBitxor)
+
+        self.check_const_fold('1&3&5', 1, ASTBitand)
+        self.check_const_fold('1|3|5', 7, ASTBitor)
+        self.check_const_fold('1^3^5', 7, ASTBitxor)
+
+    def test_binaryfold(self):
+        from parser import ASTAdd, ASTSub, ASTMul, ASTDiv
+
+        self.check_const_fold('1+3', 4, ASTAdd)
+        self.check_const_fold('"1"+"3"', '13', ASTAdd)
+        self.check_const_fold('1+3+6', 10, ASTAdd)
+
+        self.check_const_fold('1+3-6', -2)
+
+    def test_constant_tuples(self):
+        from parser import ASTTuple
+
+        self.check_const_fold('(1+1, 2)', (2, 2), ASTTuple)
+        self.check_const_fold('((1,) + (1, 2),)', ((1, 1, 2),), ASTTuple)
+
+        
+



More information about the Pypy-commit mailing list