[pypy-svn] r12939 - in pypy/dist/pypy: annotation rpython rpython/test translator/test
arigo at codespeak.net
arigo at codespeak.net
Tue May 31 19:13:21 CEST 2005
Author: arigo
Date: Tue May 31 19:13:21 2005
New Revision: 12939
Modified:
pypy/dist/pypy/annotation/bookkeeper.py
pypy/dist/pypy/annotation/builtin.py
pypy/dist/pypy/annotation/listdef.py
pypy/dist/pypy/rpython/rbuiltin.py
pypy/dist/pypy/rpython/rint.py
pypy/dist/pypy/rpython/rlist.py
pypy/dist/pypy/rpython/test/test_rlist.py
pypy/dist/pypy/translator/test/test_annrpython.py
Log:
Support for range objects in the rtyper, based on the annotator's deduction of
whether a variable can only contain a list which is a range with a known step.
Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py (original)
+++ pypy/dist/pypy/annotation/bookkeeper.py Tue May 31 19:13:21 2005
@@ -87,18 +87,19 @@
self.userclasseslist.append(cdef)
return self.userclasses[cls]
- def getlistdef(self):
+ def getlistdef(self, **flags):
"""Get the ListDef associated with the current position."""
try:
listdef = self.listdefs[self.position_key]
except KeyError:
listdef = self.listdefs[self.position_key] = ListDef(self)
+ listdef.listitem.__dict__.update(flags)
return listdef
- def newlist(self, *s_values):
+ def newlist(self, *s_values, **flags):
"""Make a SomeList associated with the current position, general
enough to contain the s_values as items."""
- listdef = self.getlistdef()
+ listdef = self.getlistdef(**flags)
for s_value in s_values:
listdef.generalize(s_value)
return SomeList(listdef)
Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py (original)
+++ pypy/dist/pypy/annotation/builtin.py Tue May 31 19:13:21 2005
@@ -38,7 +38,27 @@
# ____________________________________________________________
def builtin_range(*args):
- return getbookkeeper().newlist(SomeInteger()) # XXX nonneg=...
+ s_step = immutablevalue(1)
+ if len(args) == 1:
+ s_start = immutablevalue(0)
+ s_stop = args[0]
+ elif len(args) == 2:
+ s_start, s_stop = args
+ elif len(args) == 3:
+ s_start, s_stop = args[:2]
+ s_step = args[2]
+ else:
+ raise Exception, "range() takes 1 to 3 arguments"
+ if not s_step.is_constant():
+ raise Exception, "range() step argument should be a constant"
+ step = s_step.const
+ if step == 0:
+ raise Exception, "range() with step zero"
+ elif step > 0:
+ nonneg = s_start.nonneg
+ else:
+ nonneg = s_stop.nonneg or (s_stop.is_constant() and s_stop.const >= -1)
+ return getbookkeeper().newlist(SomeInteger(nonneg=nonneg), range_step=step)
builtin_xrange = builtin_range # xxx for now allow it
Modified: pypy/dist/pypy/annotation/listdef.py
==============================================================================
--- pypy/dist/pypy/annotation/listdef.py (original)
+++ pypy/dist/pypy/annotation/listdef.py Tue May 31 19:13:21 2005
@@ -5,6 +5,7 @@
class ListItem:
mutated = False # True for lists mutated after creation
resized = False # True for lists resized after creation
+ range_step = None # the step -- only for lists only created by a range()
def __init__(self, bookkeeper, s_value):
self.s_value = s_value
@@ -18,6 +19,8 @@
raise UnionError("merging list/dict items")
self.mutated |= other.mutated
self.resized |= other.resized
+ if other.range_step != self.range_step:
+ self.range_step = None
self.itemof.update(other.itemof)
self.read_locations.update(other.read_locations)
self.patch() # which should patch all refs to 'other'
Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py (original)
+++ pypy/dist/pypy/rpython/rbuiltin.py Tue May 31 19:13:21 2005
@@ -3,6 +3,7 @@
from pypy.rpython.lltype import malloc, typeOf, nullptr, nullgcptr
from pypy.rpython.lltype import Void, Signed
from pypy.rpython.rtyper import TyperError
+from pypy.rpython.rlist import rtype_builtin_range
class __extend__(SomeBuiltin):
@@ -60,6 +61,8 @@
assert hop.nb_args == 1
return hop.args_s[0].rtype_float(hop)
+#def rtype_builtin_range(hop): see rlist.py
+
# collect all functions
import __builtin__
Modified: pypy/dist/pypy/rpython/rint.py
==============================================================================
--- pypy/dist/pypy/rpython/rint.py (original)
+++ pypy/dist/pypy/rpython/rint.py Tue May 31 19:13:21 2005
@@ -46,6 +46,10 @@
return _rtype_template(hop, 'div')
rtype_inplace_div = rtype_div
+ def rtype_floordiv(_, hop):
+ return _rtype_template(hop, 'floordiv')
+ rtype_inplace_floordiv = rtype_floordiv
+
def rtype_mod(_, hop):
return _rtype_template(hop, 'mod')
rtype_inplace_mod = rtype_mod
Modified: pypy/dist/pypy/rpython/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/rlist.py (original)
+++ pypy/dist/pypy/rpython/rlist.py Tue May 31 19:13:21 2005
@@ -1,5 +1,6 @@
from pypy.annotation.pairtype import pair, pairtype
from pypy.annotation.model import SomeList, SomeInteger
+from pypy.objspace.flow.model import Constant
from pypy.rpython.lltype import *
# ____________________________________________________________
@@ -13,22 +14,45 @@
# 'items' points to a C-like array in memory preceded by a 'length' header,
# where each item contains a primitive value or pointer to the actual list
# item.
+#
+# Lists returned by range() and never mutated use a simpler implementation:
+#
+# struct range {
+# Signed start, stop; // step is always constant
+# }
+
+RANGE = GcStruct("range", ("start", Signed), ("stop", Signed))
+
class __extend__(SomeList):
+ def ll_range_step(s_list):
+ return (not s_list.listdef.listitem.mutated
+ and s_list.listdef.listitem.range_step)
+
def lowleveltype(s_list):
- ITEM = s_list.get_s_items().lowleveltype()
- LIST = GcStruct("list", ("items", GcPtr(GcArray(("item", ITEM)))))
- return GcPtr(LIST)
+ if s_list.ll_range_step():
+ assert isinstance(s_list.get_s_items(), SomeInteger)
+ return GcPtr(RANGE)
+ else:
+ ITEM = s_list.get_s_items().lowleveltype()
+ LIST = GcStruct("list", ("items", GcPtr(GcArray(("item", ITEM)))))
+ return GcPtr(LIST)
def get_s_items(s_list):
return s_list.listdef.listitem.s_value
def rtype_len(s_lst, hop):
v_lst, = hop.inputargs(s_lst)
- return hop.gendirectcall(ll_len, v_lst)
+ step = s_lst.ll_range_step()
+ if step:
+ cstep = hop.inputconst(Signed, step)
+ return hop.gendirectcall(ll_rangelen, v_lst, cstep)
+ else:
+ return hop.gendirectcall(ll_len, v_lst)
def rtype_method_append(s_lst, hop):
+ assert not s_lst.ll_range_step()
v_lst, v_value = hop.inputargs(s_lst, s_lst.get_s_items())
hop.gendirectcall(ll_append, v_lst, v_value)
@@ -37,11 +61,16 @@
def rtype_getitem((s_lst1, s_int2), hop):
v_lst, v_index = hop.inputargs(s_lst1, Signed)
- if s_int2.nonneg:
- llfn = ll_getitem_nonneg
+ step = s_lst1.ll_range_step()
+ if step:
+ cstep = hop.inputconst(Signed, step)
+ return hop.gendirectcall(ll_rangeitem, v_lst, v_index, cstep)
else:
- llfn = ll_getitem
- return hop.gendirectcall(llfn, v_lst, v_index)
+ if s_int2.nonneg:
+ llfn = ll_getitem_nonneg
+ else:
+ llfn = ll_getitem
+ return hop.gendirectcall(llfn, v_lst, v_index)
# ____________________________________________________________
@@ -71,9 +100,36 @@
i += len(l.items)
return l.items[i].item
+def ll_setitem(l, i, newitem):
+ if i<0:
+ i += len(l.items)
+ l.items[i].item = newitem
+
def ll_setitem_nonneg(l, i, newitem):
l.items[i].item = newitem
+# __________ range __________
+
+def ll_rangelen(l, step):
+ if step > 0:
+ result = (l.stop - l.start + (step-1)) // step
+ else:
+ result = (l.start - l.stop - (step+1)) // (-step)
+ if result < 0:
+ result = 0
+ return result
+
+def ll_rangeitem(l, i, step):
+ if i<0:
+ # XXX ack. cannot call ll_rangelen() here for now :-(
+ if step > 0:
+ length = (l.stop - l.start + (step-1)) // step
+ else:
+ length = (l.start - l.stop - (step+1)) // (-step)
+ #assert length >= 0
+ i += length
+ return l.start + i*step
+
# ____________________________________________________________
#
# Irregular operations.
@@ -95,3 +151,24 @@
v_item = hop.inputarg(s_listitem, arg=i)
hop.gendirectcall(ll_setitem_nonneg, v_result, ci, v_item)
return v_result
+
+def ll_newrange(start, stop):
+ l = malloc(RANGE)
+ l.start = start
+ l.stop = stop
+ return l
+
+def rtype_builtin_range(hop):
+ s_range = hop.s_result
+ step = s_range.listdef.listitem.range_step
+ if step is None: # cannot build a RANGE object, needs a real list
+ raise TyperError("range() list used too dynamically")
+ if hop.nb_args == 1:
+ vstart = hop.inputconst(Signed, 0)
+ vstop, = hop.inputargs(Signed)
+ elif hop.nb_args == 2:
+ vstart, vstop = hop.inputargs(Signed, Signed)
+ else:
+ vstart, vstop, vstep = hop.inputargs(Signed, Signed, Signed)
+ assert isinstance(vstep, Constant) and vstep.value == step
+ return hop.gendirectcall(ll_newrange, vstart, vstop)
Modified: pypy/dist/pypy/rpython/test/test_rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rlist.py (original)
+++ pypy/dist/pypy/rpython/test/test_rlist.py Tue May 31 19:13:21 2005
@@ -1,8 +1,42 @@
from pypy.translator.translator import Translator
+from pypy.annotation.listdef import ListDef
from pypy.rpython.lltype import *
from pypy.rpython.rtyper import RPythonTyper
+from pypy.rpython.rlist import *
+def test_rlist():
+ s = SomeList(ListDef(None, SomeInteger()))
+ l = ll_newlist(s.lowleveltype(), 3)
+ ll_setitem(l, 0, 42)
+ ll_setitem(l, -2, 43)
+ ll_setitem_nonneg(l, 2, 44)
+ ll_append(l, 45)
+ assert ll_getitem(l, -4) == 42
+ assert ll_getitem_nonneg(l, 1) == 43
+ assert ll_getitem(l, 2) == 44
+ assert ll_getitem(l, 3) == 45
+ assert ll_len(l) == 4
+
+def test_rlist_range():
+ def test1(start, stop, step):
+ expected = range(start, stop, step)
+ length = len(expected)
+ l = ll_newrange(start, stop)
+ assert ll_rangelen(l, step) == length
+ lst = [ll_rangeitem(l, i, step) for i in range(length)]
+ assert lst == expected
+ lst = [ll_rangeitem(l, i-length, step) for i in range(length)]
+ assert lst == expected
+
+ for start in (-10, 0, 1, 10):
+ for stop in (-8, 0, 4, 8, 25):
+ for step in (1, 2, 3, -1, -2):
+ test1(start, stop, step)
+
+
+# ____________________________________________________________
+
def test_simple():
def dummyfn():
l = [10,20,30]
@@ -42,3 +76,19 @@
typer.specialize()
#t.view()
t.checkgraphs()
+
+
+def test_range():
+ def dummyfn(N):
+ total = 0
+ total = len(range(N))
+ #for i in :
+ # total += i
+ return total
+
+ t = Translator(dummyfn)
+ t.annotate([])
+ typer = RPythonTyper(t.annotator)
+ typer.specialize()
+ #t.view()
+ t.checkgraphs()
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 Tue May 31 19:13:21 2005
@@ -736,6 +736,7 @@
if isinstance(s_value, annmodel.SomeList):
assert not s_value.listdef.listitem.resized
assert not s_value.listdef.listitem.mutated
+ assert s_value.listdef.listitem.is_range
def test_bool(self):
def f(a,b):
More information about the Pypy-commit
mailing list