[pypy-svn] rev 659 - pypy/trunk/src/pypy/objspace/std
tismer at codespeak.net
tismer at codespeak.net
Thu May 29 14:08:51 CEST 2003
Author: tismer
Date: Thu May 29 14:08:51 2003
New Revision: 659
Modified:
pypy/trunk/src/pypy/objspace/std/listobject.py
Log:
re-implemented listobject completely, similar to the CPython implementation. A lot is still missing
Modified: pypy/trunk/src/pypy/objspace/std/listobject.py
==============================================================================
--- pypy/trunk/src/pypy/objspace/std/listobject.py (original)
+++ pypy/trunk/src/pypy/objspace/std/listobject.py Thu May 29 14:08:51 2003
@@ -3,65 +3,80 @@
from sliceobject import W_SliceObject
from instmethobject import W_InstMethObject
from pypy.interpreter.extmodule import make_builtin_func
-
+from restricted_int import r_int, r_uint
class W_ListObject(W_Object):
def __init__(w_self, space, wrappeditems):
W_Object.__init__(w_self, space)
- w_self.wrappeditems = wrappeditems # a list of wrapped values
+ 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]
def __repr__(w_self):
""" representation for debugging purposes """
- reprlist = [repr(w_item) for w_item in w_self.wrappeditems]
+ reprlist = [repr(w_item) for w_item in w_self.ob_item[:self.ob_size]]
return "%s(%s)" % (w_self.__class__.__name__, ', '.join(reprlist))
def append(w_self, w_obj):
- w_self.wrappeditems.append(w_obj)
- return w_self.space.w_None
+ return list_append(w_self.space, w_self, w_obj)
+
+ def insert(w_self, w_idx, w_obj):
+ return list_insert(w_self.space, w_self, w_idx, w_obj)
def list_unwrap(space, w_list):
- items = [space.unwrap(w_item) for w_item in w_list.wrappeditems]
+ items = [space.unwrap(w_item) for w_item in w_list.ob_item[:w_list.ob_size]]
return list(items)
StdObjSpace.unwrap.register(list_unwrap, W_ListObject)
def list_is_true(space, w_list):
- return not not w_list.wrappeditems
+ return not not w_list.ob_size
StdObjSpace.is_true.register(list_is_true, W_ListObject)
def list_len(space, w_list):
- result = len(w_list.wrappeditems)
+ result = w_list.ob_size
return W_IntObject(space, result)
StdObjSpace.len.register(list_len, W_ListObject)
def getitem_list_int(space, w_list, w_index):
- items = w_list.wrappeditems
- try:
- w_item = items[w_index.intval]
- except IndexError:
+ items = w_list.ob_item
+ idx = w_index.intval
+ if idx < 0: idx += w_list.ob_size
+ if idx < 0 or idx >= w_list.ob_size:
raise OperationError(space.w_IndexError,
space.wrap("list index out of range"))
+ w_item = items[idx]
return w_item
StdObjSpace.getitem.register(getitem_list_int, W_ListObject, W_IntObject)
def getitem_list_slice(space, w_list, w_slice):
- items = w_list.wrappeditems
- w_length = space.wrap(len(items))
+ items = w_list.ob_item
+ w_length = space.wrap(w_list.ob_size)
w_start, w_stop, w_step, w_slicelength = w_slice.indices(space, w_length)
start = space.unwrap(w_start)
step = space.unwrap(w_step)
slicelength = space.unwrap(w_slicelength)
assert slicelength >= 0
- subitems = [None] * slicelength
+ w_res = W_ListObject(space, [])
+ list_resize(w_res, slicelength)
+ subitems = w_res.ob_item
for i in range(slicelength):
subitems[i] = items[start]
start += step
- return W_ListObject(space, subitems)
+ w_res.ob_size = slicelength
+ return w_res
StdObjSpace.getitem.register(getitem_list_slice, W_ListObject, W_SliceObject)
@@ -72,16 +87,39 @@
StdObjSpace.iter.register(list_iter, W_ListObject)
def list_add(space, w_list1, w_list2):
- items1 = w_list1.wrappeditems
- items2 = w_list2.wrappeditems
- return W_ListObject(space, items1 + items2)
+ 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
StdObjSpace.add.register(list_add, W_ListObject, W_ListObject)
def list_int_mul(space, w_list, w_int):
- items = w_list.wrappeditems
+ w_res = W_ListObject(space, [])
times = w_int.intval
- return W_ListObject(space, items * times)
+ src = w_list.ob_item
+ size = w_list.ob_size
+ newlen = size * times # XXX check overflow
+ list_resize(w_res, newlen)
+ 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
StdObjSpace.mul.register(list_int_mul, W_ListObject, W_IntObject)
@@ -91,45 +129,49 @@
StdObjSpace.mul.register(int_list_mul, W_IntObject, W_ListObject)
def list_eq(space, w_list1, w_list2):
- items1 = w_list1.wrappeditems
- items2 = w_list2.wrappeditems
- if len(items1) != len(items2):
+ items1 = w_list1.ob_item
+ items2 = w_list2.ob_item
+ if w_list1.ob_size != w_list2.ob_size:
return space.w_False
- for item1, item2 in zip(items1, items2):
- if not space.is_true(space.eq(item1, item2)):
+ for i in range(w_list1.ob_size):
+ if not space.is_true(space.eq(items1[i], items2[i])):
return space.w_False
return space.w_True
StdObjSpace.eq.register(list_eq, W_ListObject, W_ListObject)
-# upto here, lists are nearly identical to tuples.
-# XXX have to add over-allocation!
+# upto here, lists are nearly identical to tuples, despite the
+# fact that we now support over-allocation!
def setitem_list_int(space, w_list, w_index, w_any):
- items = w_list.wrappeditems
- try:
- items[w_index.intval] = w_any
- except IndexError:
+ items = w_list.ob_item
+ idx = w_index.intval
+ if idx < 0: idx += w_list.ob_size
+ if idx < 0 or idx >= w_list.ob_size:
raise OperationError(space.w_IndexError,
space.wrap("list index out of range"))
+ items[idx] = w_any
return space.w_None
StdObjSpace.setitem.register(setitem_list_int, W_ListObject, W_IntObject, W_ANY)
# not trivial!
def setitem_list_slice(space, w_list, w_slice, w_list2):
- items = w_list.wrappeditems
- w_length = space.wrap(len(items))
+ items = w_list.ob_item
+ w_length = space.wrap(w_list.ob_size)
w_start, w_stop, w_step, w_slicelength = w_slice.indices(space, w_length)
start = space.unwrap(w_start)
step = space.unwrap(w_step)
slicelength = space.unwrap(w_slicelength)
assert slicelength >= 0
- subitems = [None] * slicelength
+ w_res = W_ListObject(space, [])
+ list_resize(w_res, slicelength)
+ subitems = w_res.ob_item
for i in range(slicelength):
subitems[i] = items[start]
start += step
- return W_ListObject(space, subitems)
+ w_res.ob_size = slicelength
+ return w_res
StdObjSpace.setitem.register(setitem_list_slice, W_ListObject, W_SliceObject, W_ANY)
@@ -137,22 +179,110 @@
if space.is_true(space.eq(w_attr, space.wrap('append'))):
w_builtinfn = make_builtin_func(space, W_ListObject.append)
return W_InstMethObject(space, w_list, w_builtinfn)
+ if space.is_true(space.eq(w_attr, space.wrap('insert'))):
+ w_builtinfn = make_builtin_func(space, W_ListObject.insert)
+ return W_InstMethObject(space, w_list, w_builtinfn)
raise FailedToImplement(space.w_AttributeError)
StdObjSpace.getattr.register(getattr_list, W_ListObject, W_ANY)
+# 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):
+ print w_list.ob_size, w_list.ob_item
+ list_resize(w_list, w_list.ob_size+1)
+ print w_list.ob_size, w_list.ob_item
+ 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]
+ print w_list.ob_size, w_list.ob_item
+ items[where] = w_any
+ print w_list.ob_size, w_list.ob_item
+ w_list.ob_size += 1
+ print w_list.ob_size, w_list.ob_item
+
+def list_insert(space, w_list, w_where, w_any):
+ ins1(w_list, w_where.intval, w_any)
+ return space.w_None
+
+def list_append(space, w_list, w_any):
+ ins1(w_list, w_list.ob_size, w_any)
+ return space.w_None
"""
static PyMethodDef list_methods[] = {
- {"append", (PyCFunction)listappend, METH_O, append_doc},
- {"insert", (PyCFunction)listinsert, METH_VARARGS, insert_doc},
- {"extend", (PyCFunction)listextend, METH_O, extend_doc},
- {"pop", (PyCFunction)listpop, METH_VARARGS, pop_doc},
- {"remove", (PyCFunction)listremove, METH_O, remove_doc},
- {"index", (PyCFunction)listindex, METH_O, index_doc},
- {"count", (PyCFunction)listcount, METH_O, count_doc},
- {"reverse", (PyCFunction)listreverse, METH_NOARGS, reverse_doc},
- {"sort", (PyCFunction)listsort, METH_VARARGS, sort_doc},
- {NULL, NULL} /* sentinel */
+ {"append", (PyCFunction)listappend, METH_O, append_doc},
+ {"insert", (PyCFunction)listinsert, METH_VARARGS, insert_doc},
+ {"extend", (PyCFunction)listextend, METH_O, extend_doc},
+ {"pop", (PyCFunction)listpop, METH_VARARGS, pop_doc},
+ {"remove", (PyCFunction)listremove, METH_O, remove_doc},
+ {"index", (PyCFunction)listindex, METH_O, index_doc},
+ {"count", (PyCFunction)listcount, METH_O, count_doc},
+ {"reverse", (PyCFunction)listreverse, METH_NOARGS, reverse_doc},
+ {"sort", (PyCFunction)listsort, METH_VARARGS, sort_doc},
+ {NULL, NULL} /* sentinel */
};
"""
More information about the Pypy-commit
mailing list