[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