[pypy-svn] r13220 - in pypy/dist/pypy/rpython: . test
arigo at codespeak.net
arigo at codespeak.net
Thu Jun 9 10:44:43 CEST 2005
Author: arigo
Date: Thu Jun 9 10:44:40 2005
New Revision: 13220
Added:
pypy/dist/pypy/rpython/rslice.py (contents, props changed)
Modified:
pypy/dist/pypy/rpython/rlist.py
pypy/dist/pypy/rpython/rtyper.py
pypy/dist/pypy/rpython/test/test_rlist.py
Log:
Slices and getslice for lists.
Modified: pypy/dist/pypy/rpython/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/rlist.py (original)
+++ pypy/dist/pypy/rpython/rlist.py Thu Jun 9 10:44:40 2005
@@ -4,6 +4,8 @@
from pypy.rpython.lltype import *
from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr
from pypy.rpython import rrange
+from pypy.rpython.rslice import SliceRepr
+from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr
# ____________________________________________________________
#
@@ -86,6 +88,17 @@
llfn = ll_setitem
return hop.gendirectcall(llfn, v_lst, v_index, v_item)
+class __extend__(pairtype(ListRepr, SliceRepr)):
+
+ def rtype_getitem((r_lst, r_slic), hop):
+ if r_slic == startonly_slice_repr:
+ v_lst, v_start = hop.inputargs(r_lst, startonly_slice_repr)
+ return hop.gendirectcall(ll_listslice_startonly, v_lst, v_start)
+ if r_slic == startstop_slice_repr:
+ v_lst, v_slice = hop.inputargs(r_lst, startstop_slice_repr)
+ return hop.gendirectcall(ll_listslice, v_lst, v_slice)
+ raise TyperError(r_slic)
+
class __extend__(pairtype(ListRepr, ListRepr)):
def convert_from_to((r_lst1, r_lst2), v, llops):
if r_lst1.listitem is None or r_lst2.listitem is None:
@@ -170,6 +183,31 @@
j += 1
l1.items = newitems
+def ll_listslice_startonly(l1, start):
+ len1 = len(l1.items)
+ newitems = malloc(typeOf(l1).TO.items.TO, len1 - start)
+ j = 0
+ while start < len1:
+ newitems[j].item = l1.items[start].item
+ start += 1
+ j += 1
+ l = malloc(typeOf(l1).TO)
+ l.items = newitems
+ return l
+
+def ll_listslice(l1, slice):
+ start = slice.start
+ stop = slice.stop
+ newitems = malloc(typeOf(l1).TO.items.TO, stop - start)
+ j = 0
+ while start < stop:
+ newitems[j].item = l1.items[start].item
+ start += 1
+ j += 1
+ l = malloc(typeOf(l1).TO)
+ l.items = newitems
+ return l
+
# ____________________________________________________________
#
# Irregular operations.
Added: pypy/dist/pypy/rpython/rslice.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/rslice.py Thu Jun 9 10:44:40 2005
@@ -0,0 +1,75 @@
+from pypy.annotation.pairtype import pairtype
+from pypy.annotation import model as annmodel
+from pypy.objspace.flow.model import Constant
+from pypy.rpython.lltype import *
+from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr
+import sys
+
+# ____________________________________________________________
+#
+# Concrete implementation of RPython slice objects:
+#
+# - if stop is None, use only a Signed
+# - if stop is not None:
+#
+# struct slice {
+# Signed start;
+# Signed stop;
+# // step is always 1
+# }
+
+SLICE = GcStruct("slice", ("start", Signed), ("stop", Signed))
+
+
+class __extend__(annmodel.SomeSlice):
+ def rtyper_makerepr(self, rtyper):
+ if not self.step.is_constant() or self.step.const not in (None, 1):
+ raise TyperError("only supports slices with step 1")
+ if isinstance(self.start, annmodel.SomeInteger):
+ if not self.start.nonneg:
+ raise TyperError("slice start must be proved non-negative")
+ if isinstance(self.stop, annmodel.SomeInteger):
+ if not self.stop.nonneg:
+ raise TyperError("slice stop must be proved non-negative")
+ if self.stop.is_constant() and self.stop.const is None:
+ return startonly_slice_repr
+ else:
+ return startstop_slice_repr
+ def rtyper_makekey(self):
+ return self.stop.rtyper_makekey(), self.step.rtyper_makekey()
+
+
+class SliceRepr(Repr):
+ pass
+
+startstop_slice_repr = SliceRepr()
+startstop_slice_repr.lowleveltype = Ptr(SLICE)
+startonly_slice_repr = SliceRepr()
+startonly_slice_repr.lowleveltype = Signed
+
+# ____________________________________________________________
+
+def ll_newslice(start, stop):
+ s = malloc(SLICE)
+ s.start = start
+ s.stop = stop
+ return s
+
+def rtype_newslice(hop):
+ sig = []
+ for s in hop.args_s:
+ if s.is_constant() and s.const is None:
+ sig.append(Void)
+ else:
+ sig.append(Signed)
+ v_start, v_stop, v_step = hop.inputargs(*sig)
+ assert isinstance(v_step, Constant) and v_step.value in (None, 1)
+ if isinstance(v_start, Constant) and v_start.value is None:
+ v_start = hop.inputconst(Signed, 0)
+ if isinstance(v_stop, Constant) and v_stop.value is None:
+ # start-only slice
+ # NB. cannot just return v_start in case it is a constant
+ return hop.genop('same_as', [v_start], resulttype=startonly_slice_repr)
+ else:
+ # start-stop slice
+ return hop.gendirectcall(ll_newslice, v_start, v_stop)
Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py (original)
+++ pypy/dist/pypy/rpython/rtyper.py Thu Jun 9 10:44:40 2005
@@ -251,6 +251,9 @@
def translate_op_newtuple(self, hop):
return rtuple.rtype_newtuple(hop)
+ def translate_op_newslice(self, hop):
+ return rslice.rtype_newslice(hop)
+
def missing_operation(self, hop):
raise TyperError("unimplemented operation: '%s'" % hop.spaceop.opname)
@@ -410,6 +413,7 @@
# and the rtyper_chooserepr() methods
from pypy.rpython import robject
from pypy.rpython import rint, rbool, rfloat
+from pypy.rpython import rslice
from pypy.rpython import rlist, rstr, rtuple
from pypy.rpython import rbuiltin, rpbc
from pypy.rpython import rptr
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 Thu Jun 9 10:44:40 2005
@@ -2,10 +2,11 @@
from pypy.rpython.lltype import *
from pypy.rpython.rtyper import RPythonTyper
from pypy.rpython.rlist import *
+from pypy.rpython.rslice import ll_newslice
from pypy.rpython.rint import signed_repr
-def test_rlist():
+def sample_list():
rlist = ListRepr(signed_repr)
rlist.setup()
l = ll_newlist(rlist.lowleveltype, 3)
@@ -13,20 +14,41 @@
ll_setitem(l, -2, 43)
ll_setitem_nonneg(l, 2, 44)
ll_append(l, 45)
+ return l
+
+def check_list(l1, expected):
+ assert ll_len(l1) == len(expected)
+ for i, x in zip(range(len(expected)), expected):
+ assert ll_getitem_nonneg(l1, i) == x
+
+def test_rlist_basic():
+ l = sample_list()
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
+ check_list(l, [42, 43, 44, 45])
+
+def test_rlist_extend_concat():
+ l = sample_list()
ll_extend(l, l)
- assert ll_len(l) == 8
- for i, x in zip(range(8), [42, 43, 44, 45, 42, 43, 44, 45]):
- assert ll_getitem_nonneg(l, i) == x
+ check_list(l, [42, 43, 44, 45] * 2)
l1 = ll_concat(l, l)
assert l1 != l
- assert ll_len(l1) == 16
- for i, x in zip(range(16), [42, 43, 44, 45] * 4):
- assert ll_getitem_nonneg(l1, i) == x
+ check_list(l1, [42, 43, 44, 45] * 4)
+
+def test_rlist_slice():
+ l = sample_list()
+ check_list(ll_listslice_startonly(l, 0), [42, 43, 44, 45])
+ check_list(ll_listslice_startonly(l, 1), [43, 44, 45])
+ check_list(ll_listslice_startonly(l, 2), [44, 45])
+ check_list(ll_listslice_startonly(l, 3), [45])
+ check_list(ll_listslice_startonly(l, 4), [])
+ for start in range(5):
+ for stop in range(start, 5):
+ s = ll_newslice(start, stop)
+ check_list(ll_listslice(l, s), [42, 43, 44, 45][start:stop])
# ____________________________________________________________
@@ -83,3 +105,9 @@
l += [6,7]
return l + [8]
rtype(dummyfn)
+
+def test_slice():
+ def dummyfn():
+ l = [5, 6, 7, 8, 9]
+ return l[:2], l[1:4], l[3:]
+ rtype(dummyfn).view()
More information about the Pypy-commit
mailing list