[pypy-svn] r17298 - in pypy/dist/pypy: objspace/std objspace/std/test rpython rpython/test translator/c
tismer at codespeak.net
tismer at codespeak.net
Tue Sep 6 19:32:52 CEST 2005
Author: tismer
Date: Tue Sep 6 19:32:48 2005
New Revision: 17298
Modified:
pypy/dist/pypy/objspace/std/listobject.py
pypy/dist/pypy/objspace/std/marshal_impl.py
pypy/dist/pypy/objspace/std/test/test_listobject.py
pypy/dist/pypy/rpython/rlist.py
pypy/dist/pypy/rpython/rtuple.py
pypy/dist/pypy/rpython/test/test_rlist.py
pypy/dist/pypy/translator/c/extfunc.py
Log:
quite a big check-in, this was not my intent.
I removed overallocation from listobject.py
and tried to map as much as possible directly to rlist.py
Also did some simplifications and additions to rlist,
which unfortunately affected quite some code.
new: rlist supports inplace multiplication.
rlist.pop specializes on error checking, now.
The latter causes the rtyper to break. I'm checking in, since
this looks like a bug in rtyper.
Modified: pypy/dist/pypy/objspace/std/listobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/listobject.py (original)
+++ pypy/dist/pypy/objspace/std/listobject.py Tue Sep 6 19:32:48 2005
@@ -14,31 +14,18 @@
def __init__(w_self, space, wrappeditems):
W_Object.__init__(w_self, space)
- w_self.ob_item = []
- w_self.ob_size = 0
- newlen = len(wrappeditems)
- _list_resize(w_self, newlen)
- w_self.ob_size = newlen
- items = w_self.ob_item
- p = newlen
- while p:
- p -= 1
- items[p] = wrappeditems[p]
+ w_self.wrappeditems = wrappeditems
def __repr__(w_self):
""" representation for debugging purposes """
- reprlist = [repr(w_item) for w_item in w_self.ob_item[:w_self.ob_size]]
+ reprlist = [repr(w_item) for w_item in w_self.wrappeditems]
return "%s(%s)" % (w_self.__class__.__name__, ', '.join(reprlist))
def unwrap(w_list):
space = w_list.space
- items = [space.unwrap(w_item) for w_item in w_list.ob_item[:w_list.ob_size]]# XXX generic mixed types unwrap
+ items = [space.unwrap(w_item) for w_item in w_list.wrappeditems]# XXX generic mixed types unwrap
return list(items)
- def clear(w_list):
- w_list.ob_item = []
- w_list.ob_size = 0
-
registerimplementation(W_ListObject)
@@ -47,60 +34,45 @@
w_iterable, = __args__.parse('list',
(['sequence'], None, None), # signature
[W_ListObject(space, [])]) # default argument
- w_list.clear()
-
- length = 0
- try:
- length = space.int_w(space.len(w_iterable))
- if length < 0:
- length = 8
- except OperationError, e:
- pass # for now
- _list_resize(w_list, length)
- w_iterator = space.iter(w_iterable)
- while True:
- try:
- w_item = space.next(w_iterator)
- except OperationError, e:
- if not e.match(space, space.w_StopIteration):
- raise
- break # done
- _ins1(w_list, w_list.ob_size, w_item)
-
+ w_list.wrappeditems = space.unpackiterable(w_iterable)
def len__List(space, w_list):
- result = w_list.ob_size
+ result = len(w_list.wrappeditems)
return W_IntObject(space, result)
def getitem__List_ANY(space, w_list, w_index):
idx = space.int_w(w_index)
- if idx < 0:
- idx += w_list.ob_size
- if idx < 0 or idx >= w_list.ob_size:
+ try:
+ w_ret = w_list.wrappeditems[idx]
+ except IndexError:
raise OperationError(space.w_IndexError,
space.wrap("list index out of range"))
- w_item = w_list.ob_item[idx]
- return w_item
+ return w_ret
def getitem__List_Slice(space, w_list, w_slice):
- length = w_list.ob_size
+ # XXX consider to extend rlist's functionality?
+ length = len(w_list.wrappeditems)
start, stop, step, slicelength = slicetype.indices4(space, w_slice, length)
assert slicelength >= 0
- w_res = W_ListObject(space, [])
- _list_resize(w_res, slicelength)
- items = w_list.ob_item
- subitems = w_res.ob_item
+ if step == 1 and stop >= start >= 0:
+ assert stop >= 0
+ assert start >= 0
+ return W_ListObject(space, w_list.wrappeditems[start:stop])
+ w_res = W_ListObject(space, [None] * slicelength)
+ items = w_list.wrappeditems
+ subitems = w_res.wrappeditems
for i in range(slicelength):
subitems[i] = items[start]
start += step
- w_res.ob_size = slicelength
return w_res
def contains__List_ANY(space, w_list, w_obj):
# needs to be safe against eq_w() mutating the w_list behind our back
i = 0
- while i < w_list.ob_size:
- if space.eq_w(w_list.ob_item[i], w_obj):
+ items_w = w_list.wrappeditems
+ length = len(items_w)
+ while i < length:
+ if space.eq_w(items_w[i], w_obj):
return space.w_True
i += 1
return space.w_False
@@ -110,21 +82,7 @@
return iterobject.W_SeqIterObject(space, w_list)
def add__List_List(space, w_list1, w_list2):
- w_res = W_ListObject(space, [])
- newlen = w_list1.ob_size + w_list2.ob_size
- _list_resize(w_res, newlen)
- p = 0
- items = w_res.ob_item
- src = w_list1.ob_item
- for i in range(w_list1.ob_size):
- items[p] = src[i]
- p += 1
- src = w_list2.ob_item
- for i in range(w_list2.ob_size):
- items[p] = src[i]
- p += 1
- w_res.ob_size = p
- return w_res
+ return W_ListObject(space, w_list1.wrappeditems + w_list2.wrappeditems)
def inplace_add__List_ANY(space, w_list1, w_iterable2):
list_extend__List_ANY(space, w_list1, w_iterable2)
@@ -137,19 +95,7 @@
if e.match(space, space.w_TypeError):
raise FailedToImplement
raise
- w_res = W_ListObject(space, [])
- size = w_list.ob_size
- newlen = size * times # XXX check overflow
- _list_resize(w_res, newlen)
- src = w_list.ob_item
- items = w_res.ob_item
- p = 0
- for _ in range(times):
- for i in range(size):
- items[p] = src[i]
- p += 1
- w_res.ob_size = p
- return w_res
+ return W_ListObject(space, w_list.wrappeditems * times)
def mul__List_ANY(space, w_list, w_times):
return mul_list_times(space, w_list, w_times)
@@ -164,31 +110,19 @@
if e.match(space, space.w_TypeError):
raise FailedToImplement
raise
- if times <= 0:
- w_list.clear()
- return w_list
- size = w_list.ob_size
- newlen = size * times # XXX check overflow
- _list_resize(w_list, newlen)
- items = w_list.ob_item
- p = size
- for _ in range(1, times):
- for i in range(size):
- items[p] = items[i]
- p += 1
- w_list.ob_size = newlen
+ w_list.wrappeditems *= times
return w_list
def eq__List_List(space, w_list1, w_list2):
# needs to be safe against eq_w() mutating the w_lists behind our back
- if w_list1.ob_size != w_list2.ob_size:
+ if len(w_list1.wrappeditems) != len(w_list2.wrappeditems):
return space.w_False
i = 0
- while i < w_list1.ob_size and i < w_list2.ob_size:
- if not space.eq_w(w_list1.ob_item[i], w_list2.ob_item[i]):
+ while i < len(w_list1.wrappeditems) and i < len(w_list2.wrappeditems):
+ if not space.eq_w(w_list1.wrappeditems[i], w_list2.wrappeditems[i]):
return space.w_False
i += 1
- return space.newbool(w_list1.ob_size == w_list2.ob_size)
+ return space.newbool(len(w_list1.wrappeditems) == len(w_list2.wrappeditems))
def _min(a, b):
if a < b:
@@ -199,57 +133,55 @@
# needs to be safe against eq_w() mutating the w_lists behind our back
# Search for the first index where items are different
i = 0
- while i < w_list1.ob_size and i < w_list2.ob_size:
- w_item1 = w_list1.ob_item[i]
- w_item2 = w_list2.ob_item[i]
+ while i < len(w_list1.wrappeditems) and i < len(w_list2.wrappeditems):
+ w_item1 = w_list1.wrappeditems[i]
+ w_item2 = w_list2.wrappeditems[i]
if not space.eq_w(w_item1, w_item2):
return space.lt(w_item1, w_item2)
i += 1
# No more items to compare -- compare sizes
- return space.newbool(w_list1.ob_size < w_list2.ob_size)
+ return space.newbool(len(w_list1.wrappeditems) < len(w_list2.wrappeditems))
def gt__List_List(space, w_list1, w_list2):
# needs to be safe against eq_w() mutating the w_lists behind our back
# Search for the first index where items are different
i = 0
- while i < w_list1.ob_size and i < w_list2.ob_size:
- w_item1 = w_list1.ob_item[i]
- w_item2 = w_list2.ob_item[i]
+ while i < len(w_list1.wrappeditems) and i < len(w_list2.wrappeditems):
+ w_item1 = w_list1.wrappeditems[i]
+ w_item2 = w_list2.wrappeditems[i]
if not space.eq_w(w_item1, w_item2):
return space.gt(w_item1, w_item2)
i += 1
# No more items to compare -- compare sizes
- return space.newbool(w_list1.ob_size > w_list2.ob_size)
+ return space.newbool(len(w_list1.wrappeditems) > len(w_list2.wrappeditems))
-# upto here, lists are nearly identical to tuples, despite the
-# fact that we now support over-allocation!
def delitem__List_ANY(space, w_list, w_idx):
- i = space.int_w(w_idx)
- if i < 0:
- i += w_list.ob_size
- if i < 0 or i >= w_list.ob_size:
+ idx = space.int_w(w_idx)
+ try:
+ del w_list.wrappeditems[idx]
+ except IndexError:
raise OperationError(space.w_IndexError,
space.wrap("list deletion index out of range"))
- _del_slice(w_list, i, i+1)
return space.w_None
def delitem__List_Slice(space, w_list, w_slice):
- start, stop, step, slicelength = slicetype.indices4(space, w_slice, w_list.ob_size)
+ start, stop, step, slicelength = slicetype.indices4(space, w_slice,
+ len(w_list.wrappeditems))
if slicelength==0:
return
- if step<0:
- start = start+step*(slicelength-1)
+ if step < 0:
+ start = start + step * (slicelength-1)
step = -step
# stop is invalid
if step == 1:
_del_slice(w_list, start, start+slicelength)
else:
- items = w_list.ob_item
- n = w_list.ob_size
+ items = w_list.wrappeditems
+ n = len(items)
recycle = [None] * slicelength
i = start
@@ -267,15 +199,13 @@
recycle[discard] = items[i]
j = i+1
- while j<n:
- items[j-slicelength] = items[j]
+ while j < n:
+ items[j-slicelength] = items[j]
j += 1
- # make sure entries after ob_size are None, to avoid keeping references
- n -= slicelength
- assert n >= 0 # annotator hint
- w_list.ob_size = n
- for i in range(w_list.ob_size, n):
- items[i] = None
+ start = n - slicelength
+ assert start >= 0 # annotator hint
+ # XXX allow negative indices in rlist
+ del items[start:]
# now we can destruct recycle safely, regardless of
# side-effects to the list
del recycle[:]
@@ -284,43 +214,38 @@
def setitem__List_ANY_ANY(space, w_list, w_index, w_any):
idx = space.int_w(w_index)
- if idx < 0:
- idx += w_list.ob_size
- if idx < 0 or idx >= w_list.ob_size:
+ try:
+ w_list.wrappeditems[idx] = w_any
+ except IndexError:
raise OperationError(space.w_IndexError,
space.wrap("list index out of range"))
- w_list.ob_item[idx] = w_any
return space.w_None
def setitem__List_Slice_List(space, w_list, w_slice, w_list2):
- return _setitem_slice_helper(space, w_list, w_slice, w_list2.ob_item, w_list2.ob_size)
+ l = w_list2.wrappeditems
+ return _setitem_slice_helper(space, w_list, w_slice, l, len(l))
def setitem__List_Slice_Tuple(space, w_list, w_slice, w_tuple):
t = w_tuple.wrappeditems
return _setitem_slice_helper(space, w_list, w_slice, t, len(t))
def setitem__List_Slice_ANY(space, w_list, w_slice, w_iterable):
-## if isinstance(w_iterable, W_ListObject):
-## return _setitem_slice_helper(space, w_list, w_slice,
-## w_iterable.ob_item, w_iterable.ob_size)
-## if isinstance(w_iterable, W_TupleObject):
-## t = w_iterable.wrappeditems
-## else:
- t = space.unpackiterable(w_iterable)
- return _setitem_slice_helper(space, w_list, w_slice, t, len(t))
+ l = space.unpackiterable(w_iterable)
+ return _setitem_slice_helper(space, w_list, w_slice, l, len(l))
def _setitem_slice_helper(space, w_list, w_slice, sequence2, len2):
- start, stop, step, slicelength = slicetype.indices4(space, w_slice, w_list.ob_size)
+ oldsize = len(w_list.wrappeditems)
+ start, stop, step, slicelength = slicetype.indices4(space, w_slice,
+ oldsize)
assert slicelength >= 0
+ items = w_list.wrappeditems
if step == 1: # Support list resizing for non-extended slices
- oldsize = w_list.ob_size
delta = len2 - slicelength
if delta >= 0:
newsize = oldsize + delta
- _list_resize(w_list, newsize)
- w_list.ob_size = newsize
- items = w_list.ob_item
+ # XXX support this in rlist!
+ items += [None] * delta
for i in range(newsize-1, start+len2-1, -1):
items[i] = items[i-delta]
else:
@@ -331,7 +256,6 @@
"assign sequence of size %d to extended slice of size %d" %
(len2,slicelength)))
- items = w_list.ob_item
if sequence2 is items:
if step > 0:
# Always copy starting from the right to avoid
@@ -366,7 +290,7 @@
listrepr = app.interphook("listrepr")
def repr__List(space, w_list):
- if w_list.ob_size == 0:
+ if len(w_list.wrappeditems) == 0:
return space.wrap('[]')
w_currently_in_repr = space.getexecutioncontext()._py_repr
return listrepr(space, w_currently_in_repr, w_list)
@@ -374,101 +298,22 @@
def hash__List(space,w_list):
raise OperationError(space.w_TypeError,space.wrap("list objects are unhashable"))
-# adapted C code
-def _roundupsize(n):
- nbits = r_uint(0)
- n2 = n >> 5
-
-## /* Round up:
-## * If n < 256, to a multiple of 8.
-## * If n < 2048, to a multiple of 64.
-## * If n < 16384, to a multiple of 512.
-## * If n < 131072, to a multiple of 4096.
-## * If n < 1048576, to a multiple of 32768.
-## * If n < 8388608, to a multiple of 262144.
-## * If n < 67108864, to a multiple of 2097152.
-## * If n < 536870912, to a multiple of 16777216.
-## * ...
-## * If n < 2**(5+3*i), to a multiple of 2**(3*i).
-## *
-## * This over-allocates proportional to the list size, making room
-## * for additional growth. The over-allocation is mild, but is
-## * enough to give linear-time amortized behavior over a long
-## * sequence of appends() in the presence of a poorly-performing
-## * system realloc() (which is a reality, e.g., across all flavors
-## * of Windows, with Win9x behavior being particularly bad -- and
-## * we've still got address space fragmentation problems on Win9x
-## * even with this scheme, although it requires much longer lists to
-## * provoke them than it used to).
-## */
- while 1:
- n2 >>= 3
- nbits += 3
- if not n2 :
- break
- return ((n >> nbits) + 1) << nbits
-
-# before we have real arrays,
-# we use lists, allocated to fixed size.
-# XXX memory overflow is ignored here.
-# See listobject.c for reference.
-
-for_later = """
-#define NRESIZE(var, type, nitems) \
-do { \
- size_t _new_size = _roundupsize(nitems); \
- if (_new_size <= ((~(size_t)0) / sizeof(type))) \
- PyMem_RESIZE(var, type, _new_size); \
- else \
- var = NULL; \
-} while (0)
-"""
-
-def _list_resize(w_list, newlen):
- if newlen > len(w_list.ob_item):
- true_size = _roundupsize(newlen)
- old_items = w_list.ob_item
- w_list.ob_item = items = [None] * true_size
- for p in range(len(old_items)):
- items[p] = old_items[p]
-
-def _ins1(w_list, where, w_any):
- _list_resize(w_list, w_list.ob_size+1)
- size = w_list.ob_size
- items = w_list.ob_item
- if where < 0:
- where += size
- if where < 0:
- where = 0
- if (where > size):
- where = size
- for i in range(size, where, -1):
- items[i] = items[i-1]
- items[where] = w_any
- w_list.ob_size += 1
-
def list_insert__List_ANY_ANY(space, w_list, w_where, w_any):
- _ins1(w_list, space.int_w(w_where), w_any)
+ w_list.wrappeditems.insert(space.int_w(w_where), w_any)
return space.w_None
def list_append__List_ANY(space, w_list, w_any):
- _ins1(w_list, w_list.ob_size, w_any)
+ w_list.wrappeditems.append(w_any)
return space.w_None
def list_extend__List_ANY(space, w_list, w_any):
- lis = space.unpackiterable(w_any)
- newlen = w_list.ob_size + len(lis)
- _list_resize(w_list, newlen)
- d = w_list.ob_size
- items = w_list.ob_item
- for i in range(len(lis)):
- items[d+i] = lis[i]
- w_list.ob_size = newlen
+ w_list.wrappeditems += space.unpackiterable(w_any)
return space.w_None
def _del_slice(w_list, ilow, ihigh):
""" similar to the deletion part of list_ass_slice in CPython """
- n = w_list.ob_size
+ items = w_list.wrappeditems
+ n = len(items)
if ilow < 0:
ilow = 0
elif ilow > n:
@@ -477,46 +322,36 @@
ihigh = ilow
elif ihigh > n:
ihigh = n
- items = w_list.ob_item
- d = ihigh-ilow
# keep a reference to the objects to be removed,
# preventing side effects during destruction
- recycle = [items[i] for i in range(ilow, ihigh)]
- for i in range(ilow, n - d):
- items[i] = items[i+d]
- items[i+d] = None
- # make sure entries after ob_size-d are None, to avoid keeping references
- # (the above loop already set to None all items[ilow+d:old_style])
- n -= d
- assert n >= 0 # annotator hint
- w_list.ob_size = n
- for i in range(n, ilow + d):
- items[i] = None
+ recycle = items[ilow:ihigh]
+ del items[ilow:ihigh]
# now we can destruct recycle safely, regardless of
# side-effects to the list
del recycle[:]
# note that the default value will come back wrapped!!!
def list_pop__List_ANY(space, w_list, w_idx=-1):
- if w_list.ob_size == 0:
+ items = w_list.wrappeditems
+ if len(items)== 0:
raise OperationError(space.w_IndexError,
space.wrap("pop from empty list"))
- i = space.int_w(w_idx)
- if i < 0:
- i += w_list.ob_size
- if i < 0 or i >= w_list.ob_size:
+ idx = space.int_w(w_idx)
+ try:
+ w_ret = items.pop(idx)
+ except IndexError:
raise OperationError(space.w_IndexError,
space.wrap("pop index out of range"))
- w_res = w_list.ob_item[i]
- _del_slice(w_list, i, i+1)
- return w_res
+ return w_ret
def list_remove__List_ANY(space, w_list, w_any):
# needs to be safe against eq_w() mutating the w_list behind our back
i = 0
- while i < w_list.ob_size:
- if space.eq_w(w_list.ob_item[i], w_any):
- _del_slice(w_list, i, i+1)
+ items = w_list.wrappeditems
+ length = len(items)
+ while i < length:
+ if space.eq_w(items[i], w_any):
+ del items[i]
return space.w_None
i += 1
raise OperationError(space.w_ValueError,
@@ -524,13 +359,14 @@
def list_index__List_ANY_ANY_ANY(space, w_list, w_any, w_start, w_stop):
# needs to be safe against eq_w() mutating the w_list behind our back
- size = w_list.ob_size
+ items = w_list.wrappeditems
+ size = len(items)
w_start = slicetype.adapt_bound(space, w_start, space.wrap(size))
w_stop = slicetype.adapt_bound(space, w_stop, space.wrap(size))
i = space.int_w(w_start)
stop = space.int_w(w_stop)
- while i < stop and i < w_list.ob_size:
- if space.eq_w(w_list.ob_item[i], w_any):
+ while i < stop and i < len(items):
+ if space.eq_w(items[i], w_any):
return space.wrap(i)
i += 1
raise OperationError(space.w_ValueError,
@@ -540,14 +376,22 @@
# needs to be safe against eq_w() mutating the w_list behind our back
count = 0
i = 0
- while i < w_list.ob_size:
- if space.eq_w(w_list.ob_item[i], w_any):
+ items = w_list.wrappeditems
+ while i < len(items):
+ if space.eq_w(items[i], w_any):
count += 1
i += 1
return space.wrap(count)
+def list_reverse__List(space, w_list):
+ w_list.wrappeditems.reverse()
+ return space.w_None
+
+# ____________________________________________________________
+# Sorting
+
# Reverse a slice of a list in place, from lo up to (exclusive) hi.
-# (also used in sort, later)
+# (used in sort)
def _reverse_slice(lis, lo, hi):
hi -= 1
@@ -558,14 +402,6 @@
lo += 1
hi -= 1
-def list_reverse__List(space, w_list):
- if w_list.ob_size > 1:
- _reverse_slice(w_list.ob_item, 0, w_list.ob_size)
- return space.w_None
-
-# ____________________________________________________________
-# Sorting
-
class KeyContainer(baseobjspace.W_Root):
def __init__(self, w_key, w_item):
self.w_key = w_key
@@ -623,8 +459,8 @@
sorterclass = CustomKeySort
else:
sorterclass = SimpleSort
-
- sorter = sorterclass(w_list.ob_item, w_list.ob_size)
+ items = w_list.wrappeditems
+ sorter = sorterclass(items, len(items))
sorter.space = space
sorter.w_cmp = w_cmp
@@ -632,8 +468,8 @@
# The list is temporarily made empty, so that mutations performed
# by comparison functions can't affect the slice of memory we're
# sorting (allowing mutations during sorting is an IndexError or
- # core-dump factory, since ob_item may change).
- w_list.clear()
+ # core-dump factory, since wrappeditems may change).
+ w_list.wrappeditems = []
# wrap each item in a KeyContainer if needed
if has_key:
@@ -663,11 +499,10 @@
sorter.list[i] = w_obj.w_item
# check if the user mucked with the list during the sort
- mucked = len(w_list.ob_item) > 0
+ mucked = len(w_list.wrappeditems) > 0
# put the items back into the list
- w_list.ob_item = sorter.list
- w_list.ob_size = sorter.listlength
+ w_list.wrappeditems = sorter.list
if mucked:
raise OperationError(space.w_ValueError,
Modified: pypy/dist/pypy/objspace/std/marshal_impl.py
==============================================================================
--- pypy/dist/pypy/objspace/std/marshal_impl.py (original)
+++ pypy/dist/pypy/objspace/std/marshal_impl.py Tue Sep 6 19:32:48 2005
@@ -318,7 +318,8 @@
def marshal_w__Tuple(space, w_tuple, m):
m.start(TYPE_TUPLE)
- m.put_list_w(w_tuple.wrappeditems, len(w_tuple.wrappeditems))
+ items = w_tuple.wrappeditems
+ m.put_list_w(items, len(items))
def unmarshal_Tuple(space, u, tc):
items_w = u.get_list_w()
@@ -327,8 +328,8 @@
def marshal_w__List(space, w_list, m):
m.start(TYPE_LIST)
- n = w_list.ob_size
- m.put_list_w(w_list.ob_item, w_list.ob_size)
+ items = w_list.wrappeditems
+ m.put_list_w(items, len(items))
def unmarshal_List(space, u, tc):
items_w = u.get_list_w()
@@ -488,7 +489,6 @@
w_lis = set_to_list(space, w_set)
# cannot access this list directly, because it's
# type is not exactly known through applevel.
- # otherwise, I would access ob_item and ob_size, directly.
lis_w = space.unpackiterable(w_lis)
m.start(TYPE_SET)
m.put_list_w(lis_w, len(lis_w))
Modified: pypy/dist/pypy/objspace/std/test/test_listobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/test_listobject.py (original)
+++ pypy/dist/pypy/objspace/std/test/test_listobject.py Tue Sep 6 19:32:48 2005
@@ -341,27 +341,6 @@
assert self.space.eq_w(self.space.le(w_list4, w_list3),
self.space.w_True)
- def test_no_unneeded_refs(self):
- space = self.space
- w = space.wrap
- w_empty = W_ListObject(space, [])
-
- w_list = W_ListObject(space, [w(5), w(3), w(99)])
- space.setitem(w_list, space.newslice(w(0), w(3), w(None)), w_empty)
- assert w_list.ob_item == [None]*len(w_list.ob_item)
-
- w_list = W_ListObject(space, [w(5), w(3), w(99)])
- space.delitem(w_list, space.newslice(w(0), w(3), w(None)))
- assert w_list.ob_item == [None]*len(w_list.ob_item)
-
- w_list = W_ListObject(space, [w(5), w(3), w(99)])
- space.call_method(w_list, 'pop')
- assert w_list.ob_item[2] is None
- space.call_method(w_list, 'pop')
- assert w_list.ob_item[1] is None
- space.call_method(w_list, 'pop')
- assert w_list.ob_item == [None]*len(w_list.ob_item)
-
class AppTestW_ListObject:
def test_call_list(self):
assert list('') == []
Modified: pypy/dist/pypy/rpython/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/rlist.py (original)
+++ pypy/dist/pypy/rpython/rlist.py Tue Sep 6 19:32:48 2005
@@ -93,7 +93,7 @@
def get_eqfunc(self):
return inputconst(Void, self.item_repr.get_ll_eq_function())
- def rtype_bltn_list(self,hop):
+ def rtype_bltn_list(self, hop):
v_lst = hop.inputarg(self, 0)
return hop.gendirectcall(ll_copy, v_lst)
@@ -141,6 +141,11 @@
hop.gendirectcall(ll_reverse,v_lst)
def rtype_method_pop(self, hop):
+ if hop.has_implicit_exception(IndexError):
+ spec = dum_checkidx
+ else:
+ spec = dum_nocheck
+ v_func = hop.inputconst(Void, spec)
if hop.nb_args == 2:
args = hop.inputargs(self, Signed)
assert hasattr(args[1], 'concretetype')
@@ -155,8 +160,8 @@
else:
args = hop.inputargs(self)
llfn = ll_pop_default
- hop.exception_cannot_occur() # no IndexError support (yet?)
- return hop.gendirectcall(llfn, *args)
+ hop.exception_is_here()
+ return hop.gendirectcall(llfn, v_func, *args)
def make_iterator_repr(self):
return ListIteratorRepr(self)
@@ -191,54 +196,57 @@
class __extend__(pairtype(ListRepr, IntegerRepr)):
def rtype_getitem((r_lst, r_int), hop):
- v_lst, v_index = hop.inputargs(r_lst, Signed)
if hop.has_implicit_exception(IndexError):
- if hop.args_s[1].nonneg:
- llfn = ll_getitem_nonneg_checked
- else:
- llfn = ll_getitem_checked
+ spec = dum_checkidx
else:
- if hop.args_s[1].nonneg:
- llfn = ll_getitem_nonneg
- else:
- llfn = ll_getitem
+ spec = dum_nocheck
+ v_func = hop.inputconst(Void, spec)
+ v_lst, v_index = hop.inputargs(r_lst, Signed)
+ if hop.args_s[1].nonneg:
+ llfn = ll_getitem_nonneg
+ else:
+ llfn = ll_getitem
hop.exception_is_here()
- return hop.gendirectcall(llfn, v_lst, v_index)
-
+ return hop.gendirectcall(llfn, v_func, v_lst, v_index)
+
def rtype_setitem((r_lst, r_int), hop):
- v_lst, v_index, v_item = hop.inputargs(r_lst, Signed, r_lst.item_repr)
if hop.has_implicit_exception(IndexError):
- if hop.args_s[1].nonneg:
- llfn = ll_setitem_nonneg_checked
- else:
- llfn = ll_setitem_checked
+ spec = dum_checkidx
else:
- if hop.args_s[1].nonneg:
- llfn = ll_setitem_nonneg
- else:
- llfn = ll_setitem
+ spec = dum_nocheck
+ v_func = hop.inputconst(Void, spec)
+ v_lst, v_index, v_item = hop.inputargs(r_lst, Signed, r_lst.item_repr)
+ if hop.args_s[1].nonneg:
+ llfn = ll_setitem_nonneg
+ else:
+ llfn = ll_setitem
hop.exception_is_here()
- return hop.gendirectcall(llfn, v_lst, v_index, v_item)
+ return hop.gendirectcall(llfn, v_func, v_lst, v_index, v_item)
def rtype_delitem((r_lst, r_int), hop):
- v_lst, v_index = hop.inputargs(r_lst, Signed)
if hop.has_implicit_exception(IndexError):
- if hop.args_s[1].nonneg:
- llfn = ll_delitem_nonneg_checked
- else:
- llfn = ll_delitem_checked
+ spec = dum_checkidx
else:
- if hop.args_s[1].nonneg:
- llfn = ll_delitem_nonneg
- else:
- llfn = ll_delitem
+ spec = dum_nocheck
+ v_func = hop.inputconst(Void, spec)
+ v_lst, v_index = hop.inputargs(r_lst, Signed)
+ if hop.args_s[1].nonneg:
+ llfn = ll_delitem_nonneg
+ else:
+ llfn = ll_delitem
hop.exception_is_here()
- return hop.gendirectcall(llfn, v_lst, v_index)
+ return hop.gendirectcall(llfn, v_func, v_lst, v_index)
def rtype_mul((r_lst, r_int), hop):
+ v_func = hop.inputconst(Void, dum_newlist)
v_lst, v_factor = hop.inputargs(r_lst, Signed)
- return hop.gendirectcall(ll_mul, v_lst, v_factor)
-
+ return hop.gendirectcall(ll_mul, v_func, v_lst, v_factor)
+
+ def rtype_inplace_mul((r_lst, r_int), hop):
+ v_func = hop.inputconst(Void, dum_inplace)
+ v_lst, v_factor = hop.inputargs(r_lst, Signed)
+ return hop.gendirectcall(ll_mul, v_func, v_lst, v_factor)
+
class __extend__(pairtype(ListRepr, SliceRepr)):
def rtype_getitem((r_lst, r_slic), hop):
@@ -417,13 +425,23 @@
index += l.length
ll_insert_nonneg(l, index, newitem)
-def ll_pop_nonneg(l, index):
+def dum_checkidx(): pass
+def dum_nocheck(): pass
+def dum_inplace():pass
+def dum_newlist():pass
+
+def ll_pop_nonneg(func, l, index):
+ if func is dum_checkidx and (index >= l.length):
+ raise IndexError
res = l.items[index]
- ll_delitem_nonneg(l, index)
+ ll_delitem_nonneg(dum_nocheck, l, index)
return res
-def ll_pop_default(l):
- index = l.length - 1
+def ll_pop_default(func, l):
+ length = l.length
+ if func is dum_checkidx and (length == 0):
+ raise IndexError
+ index = length - 1
newlength = index
items = l.items
res = items[index]
@@ -433,8 +451,11 @@
_ll_list_resize(l, newlength)
return res
-def ll_pop_zero(l):
- newlength = l.length - 1
+def ll_pop_zero(func, l):
+ length = l.length
+ if func is dum_checkidx and (length == 0):
+ raise IndexError
+ newlength = length - 1
res = l.items[0]
j = 0
items = l.items
@@ -449,77 +470,60 @@
_ll_list_resize(l, newlength)
return res
-def ll_pop(l, index):
+def ll_pop(func, l, index):
+ length = l.length
if index < 0:
- index += l.length
+ index += length
+ if func is dum_checkidx and (index < 0 or index >= length):
+ raise IndexError
res = l.items[index]
- ll_delitem_nonneg(l, index)
+ ll_delitem_nonneg(dum_nocheck, l, index)
return res
def ll_reverse(l):
length = l.length
- len2 = length // 2
i = 0
items = l.items
length_1_i = length-1-i
- while i < len2:
+ while i < length_1_i:
tmp = l.items[i]
items[i] = items[length_1_i]
items[length_1_i] = tmp
i += 1
length_1_i -= 1
-def ll_getitem_nonneg(l, i):
- return l.items[i]
-
-def ll_getitem(l, i):
- if i < 0:
- i += l.length
- return l.items[i]
-
-def ll_getitem_nonneg_checked(l, i):
- if i >= l.length:
+def ll_getitem_nonneg(func, l, index):
+ if func is dum_checkidx and (index >= l.length):
raise IndexError
- else:
- return l.items[i]
+ return l.items[index]
-def ll_getitem_checked(l, i):
- if i < 0:
- i += l.length
- if i >= l.length or i < 0:
+def ll_getitem(func, l, index):
+ length = l.length
+ if index < 0:
+ index += length
+ if func is dum_checkidx and (index < 0 or index >= length):
raise IndexError
- else:
- return l.items[i]
-
-def ll_setitem_nonneg(l, i, newitem):
- l.items[i] = newitem
+ return l.items[index]
-def ll_setitem_nonneg_checked(l, i, newitem):
- if i >= l.length:
+def ll_setitem_nonneg(func, l, index, newitem):
+ if func is dum_checkidx and (index >= l.length):
raise IndexError
- l.items[i] = newitem
+ l.items[index] = newitem
-def ll_setitem(l, i, newitem):
- if i < 0:
- i += l.length
- l.items[i] = newitem
-
-def ll_setitem_checked(l, i, newitem):
- if i < 0:
- i += l.length
- if i >= l.length or i < 0:
+def ll_setitem(func, l, index, newitem):
+ length = l.length
+ if index < 0:
+ index += length
+ if func is dum_checkidx and (index < 0 or index >= length):
raise IndexError
- else:
- l.items[i] = newitem
+ l.items[index] = newitem
-def ll_delitem_nonneg_checked(l, i):
- if i >= l.length:
+def ll_delitem_nonneg(func, l, index):
+ length = l.length
+ if func is dum_checkidx and (index < 0 or index >= length):
raise IndexError
- ll_delitem_nonneg(l, i)
-
-def ll_delitem_nonneg(l, i):
- newlength = l.length - 1
- j = i
+ newlength = length - 1
+ j = index
items = l.items
j1 = j+1
while j < newlength:
@@ -531,17 +535,10 @@
items[newlength] = nullptr(ITEM.TO)
_ll_list_resize(l, newlength)
-def ll_delitem(l, i):
+def ll_delitem(func, l, i):
if i < 0:
i += l.length
- ll_delitem_nonneg(l, i)
-
-def ll_delitem_checked(l, i):
- if i < 0:
- i += l.length
- if i >= l.length or i < 0:
- raise IndexError
- ll_delitem_nonneg(l, i)
+ ll_delitem_nonneg(func, l, i)
def ll_concat(l1, l2):
len1 = l1.length
@@ -730,25 +727,30 @@
TEMP = GcArray(Ptr(rstr.STR))
-def ll_mul(l, f):
- items = l.items
+def ll_mul(func, l, factor):
+ source = l.items
length = l.length
- if length == 0 or f <= 0:
- return ll_newlist(typeOf(l), 0)
-
- resultlen = length * f
- new_lst = ll_newlist(typeOf(l), resultlen)
+ if factor < 0:
+ factor = 0
+ resultlen = length * factor
+ if func is dum_inplace:
+ res = l
+ _ll_list_resize(res, resultlen)
+ j = length
+ else:
+ res = ll_newlist(typeOf(l), resultlen)
+ j = 0
i = 0
- new_items = new_lst.items
- j = 0
+ target = res.items
while j < resultlen:
while i < length:
- new_items[i + j] = items[i]
+ p = j + i
+ target[p] = source[i]
i += 1
j += length
- return new_lst
-
+ return res
+
# ____________________________________________________________
#
# Irregular operations.
@@ -775,10 +777,11 @@
c1 = hop.inputconst(Void, r_list.lowleveltype)
c2 = hop.inputconst(Signed, nb_args)
v_result = hop.gendirectcall(ll_newlist, c1, c2)
+ v_func = hop.inputconst(Void, dum_nocheck)
for i in range(nb_args):
ci = hop.inputconst(Signed, i)
v_item = hop.inputarg(r_listitem, arg=i)
- hop.gendirectcall(ll_setitem_nonneg, v_result, ci, v_item)
+ hop.gendirectcall(ll_setitem_nonneg, v_func, v_result, ci, v_item)
return v_result
def ll_alloc_and_set(LISTPTR, count, item):
Modified: pypy/dist/pypy/rpython/rtuple.py
==============================================================================
--- pypy/dist/pypy/rpython/rtuple.py (original)
+++ pypy/dist/pypy/rpython/rtuple.py Tue Sep 6 19:32:48 2005
@@ -55,6 +55,7 @@
c1 = inputconst(Void, hop.r_result.lowleveltype)
c2 = inputconst(Signed, nitems)
vlist = hop.gendirectcall(rlist.ll_newlist, c1, c2)
+ v_func = hop.inputconst(Void, rlist.dum_nocheck)
for index in range(nitems):
name = self.fieldnames[index]
ritem = self.items_r[index]
@@ -62,7 +63,7 @@
vitem = hop.genop('getfield', [vtup, cname], resulttype = ritem)
vitem = hop.llops.convertvar(vitem, ritem, hop.r_result.item_repr)
cindex = inputconst(Signed, index)
- hop.gendirectcall(rlist.ll_setitem_nonneg, vlist, cindex, vitem)
+ hop.gendirectcall(rlist.ll_setitem_nonneg, v_func, vlist, cindex, vitem)
return vlist
def make_iterator_repr(self):
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 Sep 6 19:32:48 2005
@@ -6,6 +6,16 @@
from pypy.rpython.rint import signed_repr
from pypy.rpython.test.test_llinterp import interpret, interpret_raises
+# undo the specialization parameter
+for n1 in 'get set del'.split():
+ for n2 in '','_nonneg':
+ name = 'll_%sitem%s' % (n1, n2)
+ globals()['_'+name] = globals()[name]
+ exec """if 1:
+ def %s(*args):
+ return _%s(dum_checkidx, *args)
+""" % (name, name)
+del n1, n2, name
def sample_list(): # [42, 43, 44, 45]
rlist = ListRepr(signed_repr)
@@ -379,6 +389,22 @@
res = interpret(fn, [arg])
assert res == fn(arg)
+def test_list_inplace_multiply():
+ def fn(i):
+ lst = [i]
+ lst *= i
+ return len(lst)
+ for arg in (1, 9, 0, -1, -27):
+ res = interpret(fn, [arg])
+ assert res == fn(arg)
+ def fn(i):
+ lst = [i, i + 1]
+ lst *= i
+ return len(lst)
+ for arg in (1, 9, 0, -1, -27):
+ res = interpret(fn, [arg])
+ assert res == fn(arg)
+
def test_indexerror():
def fn(i):
l = [5, 8, 3]
@@ -395,6 +421,33 @@
res = interpret(fn, [-2])
assert res._obj.value == "oups"
+def list_is_clear(lis, idx):
+ items = lis._obj.items._obj.items
+ for i in range(idx, len(items)):
+ if items[i]._obj is not None:
+ return False
+ return True
+
+def test_no_unneeded_refs():
+ def fndel(p, q):
+ lis = ["5", "3", "99"]
+ assert q >= 0
+ assert p >= 0
+ del lis[p:q]
+ return lis
+ def fnpop(n):
+ lis = ["5", "3", "99"]
+ while n:
+ lis.pop()
+ n -=1
+ return lis
+ for i in range(2, 3+1):
+ lis = interpret(fndel, [0, i])
+ assert list_is_clear(lis, 3-i)
+ for i in range(3):
+ lis = interpret(fnpop, [i])
+ assert list_is_clear(lis, 3-i)
+
def test_list_basic_ops():
def list_basic_ops(i=int, j=int):
l = [1,2,3]
Modified: pypy/dist/pypy/translator/c/extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/c/extfunc.py (original)
+++ pypy/dist/pypy/translator/c/extfunc.py Tue Sep 6 19:32:48 2005
@@ -93,7 +93,7 @@
def _RPyListOfString_SetItem(l=p,
index=lltype.Signed,
newstring=lltype.Ptr(STR)):
- rlist.ll_setitem_nonneg(l, index, newstring)
+ rlist.ll_setitem_nonneg(rlist.dum_nocheck, l, index, newstring)
for fname, f in locals().items():
if isinstance(f, types.FunctionType):
More information about the Pypy-commit
mailing list