[pypy-svn] r13280 - in pypy/dist/pypy: annotation translator translator/test

arigo at codespeak.net arigo at codespeak.net
Fri Jun 10 23:48:28 CEST 2005


Author: arigo
Date: Fri Jun 10 23:48:26 2005
New Revision: 13280

Modified:
   pypy/dist/pypy/annotation/binaryop.py
   pypy/dist/pypy/translator/annrpython.py
   pypy/dist/pypy/translator/test/test_annrpython.py
Log:
Teach the annotator to deduce nonneg flags from code like "if i >= 0:...".
Exposed a bug in the two oldest tests we have for the annotator, which build a
graph by hand, reusing the same variable multiple times :-(



Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Fri Jun 10 23:48:26 2005
@@ -2,6 +2,7 @@
 Binary operations between SomeValues.
 """
 
+import operator
 from pypy.annotation.pairtype import pair, pairtype
 from pypy.annotation.model import SomeObject, SomeInteger, SomeBool
 from pypy.annotation.model import SomeString, SomeChar, SomeList, SomeDict
@@ -13,7 +14,7 @@
 from pypy.annotation.model import add_knowntypedata, merge_knowntypedata
 from pypy.annotation.bookkeeper import getbookkeeper
 from pypy.annotation.classdef import isclassdef
-from pypy.objspace.flow.model import Constant
+from pypy.objspace.flow.model import Constant, Variable
 
 # convenience only!
 def immutablevalue(x):
@@ -235,6 +236,38 @@
     pow.can_only_throw = [ZeroDivisionError]
     pow_ovf = _clone(pow, [ZeroDivisionError, OverflowError])
 
+    def _compare_helper((int1, int2), opname, operation):
+        if int1.is_constant() and int2.is_constant():
+            r = immutablevalue(operation(int1.const, int2.const))
+        else:
+            r = SomeBool()
+        knowntypedata = {}
+        # XXX HACK HACK HACK
+        # propagate nonneg information between the two arguments
+        fn, block, i = getbookkeeper().position_key
+        op = block.operations[i]
+        assert op.opname == opname
+        assert len(op.args) == 2
+        if int1.nonneg and isinstance(op.args[1], Variable):
+            case = opname in ('lt', 'le', 'eq')
+            add_knowntypedata(knowntypedata, case, [op.args[1]],
+                              SomeInteger(nonneg=True))
+        if int2.nonneg and isinstance(op.args[0], Variable):
+            case = opname in ('gt', 'ge', 'eq')
+            add_knowntypedata(knowntypedata, case, [op.args[0]],
+                              SomeInteger(nonneg=True))
+        if knowntypedata:
+            r.knowntypedata = knowntypedata
+        return r
+
+    def lt(intint): return intint._compare_helper('lt', operator.lt)
+    def le(intint): return intint._compare_helper('le', operator.le)
+    def eq(intint): return intint._compare_helper('eq', operator.eq)
+    def ne(intint): return intint._compare_helper('ne', operator.ne)
+    def gt(intint): return intint._compare_helper('gt', operator.gt)
+    def ge(intint): return intint._compare_helper('ge', operator.ge)
+
+
 class __extend__(pairtype(SomeBool, SomeBool)):
 
     def union((boo1, boo2)):

Modified: pypy/dist/pypy/translator/annrpython.py
==============================================================================
--- pypy/dist/pypy/translator/annrpython.py	(original)
+++ pypy/dist/pypy/translator/annrpython.py	Fri Jun 10 23:48:26 2005
@@ -7,7 +7,7 @@
 from pypy.annotation.bookkeeper import Bookkeeper
 from pypy.objspace.flow.model import Variable, Constant
 from pypy.objspace.flow.model import SpaceOperation, FunctionGraph
-from pypy.objspace.flow.model import last_exception
+from pypy.objspace.flow.model import last_exception, checkgraph
 
 class AnnotatorError(Exception):
     pass
@@ -86,6 +86,7 @@
         """Recursively build annotations about the specific entry point."""
         if isinstance(func_or_flowgraph, FunctionGraph):
             flowgraph = func_or_flowgraph
+            checkgraph(flowgraph)
             self._register_returnvar(flowgraph, func)
         else:
             func = func_or_flowgraph

Modified: pypy/dist/pypy/translator/test/test_annrpython.py
==============================================================================
--- pypy/dist/pypy/translator/test/test_annrpython.py	(original)
+++ pypy/dist/pypy/translator/test/test_annrpython.py	Fri Jun 10 23:48:26 2005
@@ -80,20 +80,22 @@
                 i = i - 1
             return i
         """
-        i = Variable("i")
+        i1 = Variable("i1")
+        i2 = Variable("i2")
+        i3 = Variable("i3")
         conditionres = Variable("conditionres")
-        conditionop = SpaceOperation("gt", [i, Constant(0)], conditionres)
-        decop = SpaceOperation("add", [i, Constant(-1)], i)
-        headerblock = Block([i])
-        whileblock = Block([i])
+        conditionop = SpaceOperation("gt", [i1, Constant(0)], conditionres)
+        decop = SpaceOperation("add", [i2, Constant(-1)], i3)
+        headerblock = Block([i1])
+        whileblock = Block([i2])
 
         fun = FunctionGraph("f", headerblock)
         headerblock.operations.append(conditionop)
         headerblock.exitswitch = conditionres
-        headerblock.closeblock(Link([i], fun.returnblock, False),
-                               Link([i], whileblock, True))
+        headerblock.closeblock(Link([i1], fun.returnblock, False),
+                               Link([i1], whileblock, True))
         whileblock.operations.append(decop)
-        whileblock.closeblock(Link([i], headerblock))
+        whileblock.closeblock(Link([i3], headerblock))
 
         a = self.RPythonAnnotator()
         a.build_types(fun, [int])
@@ -109,26 +111,31 @@
                 i = i - 1
             return sum
         """
-        i = Variable("i")
-        sum = Variable("sum")
+        i1 = Variable("i1")
+        i2 = Variable("i2")
+        i3 = Variable("i3")
+        i4 = Variable("i4")
+        sum2 = Variable("sum2")
+        sum3 = Variable("sum3")
+        sum4 = Variable("sum4")
 
         conditionres = Variable("conditionres")
-        conditionop = SpaceOperation("gt", [i, Constant(0)], conditionres)
-        decop = SpaceOperation("add", [i, Constant(-1)], i)
-        addop = SpaceOperation("add", [i, sum], sum)
-        startblock = Block([i])
-        headerblock = Block([i, sum])
-        whileblock = Block([i, sum])
+        conditionop = SpaceOperation("gt", [i2, Constant(0)], conditionres)
+        decop = SpaceOperation("add", [i3, Constant(-1)], i4)
+        addop = SpaceOperation("add", [i3, sum3], sum4)
+        startblock = Block([i1])
+        headerblock = Block([i2, sum2])
+        whileblock = Block([i3, sum3])
 
         fun = FunctionGraph("f", startblock)
-        startblock.closeblock(Link([i, Constant(0)], headerblock))
+        startblock.closeblock(Link([i1, Constant(0)], headerblock))
         headerblock.operations.append(conditionop)
         headerblock.exitswitch = conditionres
-        headerblock.closeblock(Link([sum], fun.returnblock, False),
-                               Link([i, sum], whileblock, True))
+        headerblock.closeblock(Link([sum2], fun.returnblock, False),
+                               Link([i2, sum2], whileblock, True))
         whileblock.operations.append(addop)
         whileblock.operations.append(decop)
-        whileblock.closeblock(Link([i, sum], headerblock))
+        whileblock.closeblock(Link([i4, sum4], headerblock))
 
         a = self.RPythonAnnotator()
         a.build_types(fun, [int])
@@ -1177,7 +1184,7 @@
     def test_prime(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.prime, [int])
-        assert s == annmodel.SomeBool()
+        assert s.knowntype == bool
 
     def test_and_is_true_coalesce(self):
         def f(a,b,c,d,e):
@@ -1238,8 +1245,25 @@
         a = self.RPythonAnnotator()
         s = a.build_types(f, [bool])
         assert not s.is_constant()
-        
-            
+
+    def test_nonneg_cleverness(self):
+        def f(a, b, c, d, e, f, g, h):
+            if a < 0: a = 0
+            if b <= 0: b = 0
+            if c >= 0:
+                pass
+            else:
+                c = 0
+            if d < a: d = a
+            if e <= b: e = 1
+            if c > f: f = 2
+            if d >= g: g = 3
+            if h != a: h = 0
+            return a, b, c, d, e, f, g, h
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [int]*8)
+        assert s == annmodel.SomeTuple([annmodel.SomeInteger(nonneg=True)] * 8)
+
 
 def g(n):
     return [0,1,2,n]



More information about the Pypy-commit mailing list