[pypy-svn] r33473 - in pypy/dist/pypy: config module/__builtin__ objspace/std objspace/std/test
cfbolz at codespeak.net
cfbolz at codespeak.net
Thu Oct 19 19:38:22 CEST 2006
Author: cfbolz
Date: Thu Oct 19 19:38:20 2006
New Revision: 33473
Added:
pypy/dist/pypy/objspace/std/rangeobject.py
pypy/dist/pypy/objspace/std/test/test_rangeobject.py
Modified:
pypy/dist/pypy/config/pypyoption.py
pypy/dist/pypy/module/__builtin__/__init__.py
pypy/dist/pypy/module/__builtin__/functional.py
pypy/dist/pypy/objspace/std/model.py
pypy/dist/pypy/objspace/std/strjoinobject.py
Log:
adding a special range list implementation that won't actually create the list
until it is mutated (but behaves completely like the full list).
Modified: pypy/dist/pypy/config/pypyoption.py
==============================================================================
--- pypy/dist/pypy/config/pypyoption.py (original)
+++ pypy/dist/pypy/config/pypyoption.py Thu Oct 19 19:38:20 2006
@@ -91,6 +91,12 @@
default=False,
requires=[("objspace.std.withmultidict", True)]),
+ BoolOption("withrangelist",
+ "enable special range list implementation that does not "
+ "actually create the full list until the resulting "
+ "list is mutaged",
+ default=False),
+
BoolOption("oldstyle",
"specify whether the default metaclass should be classobj",
default=False, cmdline="--oldstyle"),
Modified: pypy/dist/pypy/module/__builtin__/__init__.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/__init__.py (original)
+++ pypy/dist/pypy/module/__builtin__/__init__.py Thu Oct 19 19:38:20 2006
@@ -140,6 +140,14 @@
space.setitem(builtin.w_dict, space.wrap('None'), space.w_None)
return builtin
+ def __init__(self, space, *args):
+ "NOT_RPYTHON: patches range if option withrangelist is set."
+ #XXX slightly strange that the __init__ changes a class attribute...
+ if (space.config.objspace.std.withrangelist and
+ space.config.objspace.name == "std"):
+ self.interpleveldefs["range"] = "functional.range_withrangelist"
+ MixedModule.__init__(self, space, *args)
+
def setup_after_space_initialization(self):
"""NOT_RPYTHON"""
space = self.space
Modified: pypy/dist/pypy/module/__builtin__/functional.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/functional.py (original)
+++ pypy/dist/pypy/module/__builtin__/functional.py Thu Oct 19 19:38:20 2006
@@ -92,3 +92,24 @@
range_fallback = applevel(getsource(app_range), getfile(app_range)
).interphook('range')
+
+def range_withrangelist(space, w_x, w_y=None, w_step=1):
+ """Return a list of integers in arithmetic position from start (defaults
+to zero) to stop - 1 by step (defaults to 1). Use a negative step to
+get a list in decending order."""
+ # XXX object space dependant
+ from pypy.objspace.std.rangeobject import W_RangeListObject
+ try:
+ # save duplication by redirecting every error to applevel
+ x = space.int_w(w_x)
+ if space.is_w(w_y, space.w_None):
+ start, stop = 0, x
+ else:
+ start, stop = x, space.int_w(w_y)
+ step = space.int_w(w_step)
+ howmany = get_len_of_range(start, stop, step)
+ except (OperationError, ValueError, OverflowError):
+ return range_fallback(space, w_x, w_y, w_step)
+ return W_RangeListObject(start, step, howmany)
+range_withrangelist.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root]
+
Modified: pypy/dist/pypy/objspace/std/model.py
==============================================================================
--- pypy/dist/pypy/objspace/std/model.py (original)
+++ pypy/dist/pypy/objspace/std/model.py Thu Oct 19 19:38:20 2006
@@ -16,6 +16,8 @@
"dictstrobject.W_DictStrIterObject"],
"withmultidict" : ["dictmultiobject.W_DictMultiObject",
"dictmultiobject.W_DictMultiIterObject"],
+ "withrangelist" : ["rangeobject.W_RangeListObject",
+ "rangeobject.W_RangeIterObject"],
}
class StdTypeModel:
@@ -71,6 +73,7 @@
from pypy.objspace.std import iterobject
from pypy.objspace.std import unicodeobject
from pypy.objspace.std import dictproxyobject
+ from pypy.objspace.std import rangeobject
from pypy.objspace.std import fake
import pypy.objspace.std.default # register a few catch-all multimethods
@@ -183,6 +186,11 @@
(unicodeobject.W_UnicodeObject,
strjoinobject.delegate_join2unicode)
]
+ if config.objspace.std.withrangelist:
+ self.typeorder[rangeobject.W_RangeListObject] += [
+ (listobject.W_ListObject,
+ rangeobject.delegate_range2list),
+ ]
# put W_Root everywhere
self.typeorder[W_Root] = []
Added: pypy/dist/pypy/objspace/std/rangeobject.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/std/rangeobject.py Thu Oct 19 19:38:20 2006
@@ -0,0 +1,161 @@
+from pypy.objspace.std.objspace import *
+from pypy.objspace.std.inttype import wrapint
+from pypy.objspace.std.sliceobject import W_SliceObject
+from pypy.objspace.std.listobject import W_ListObject
+
+from pypy.objspace.std import slicetype
+from pypy.interpreter import gateway, baseobjspace
+
+def length(start, stop, step):
+ if step > 0:
+ if stop <= start:
+ return 0
+ return (stop - start + step - 1)/step
+
+ else: # step must be < 0
+ if stop >= start:
+ return 0
+ return (start - stop - step - 1)/-step
+
+
+class W_RangeListObject(W_Object):
+ from pypy.objspace.std.listtype import list_typedef as typedef
+
+ def __init__(w_self, start, step, length):
+ assert step != 0
+ w_self.start = start
+ w_self.step = step
+ w_self.length = length
+ w_self.w_list = None
+
+ def force(w_self, space):
+ if w_self.w_list is not None:
+ return w_self.w_list
+ start = w_self.start
+ step = w_self.step
+ length = w_self.length
+ if not length:
+ w_self.w_list = space.newlist()
+ return w_self.w_list
+
+ arr = [0] * length # this is to avoid using append.
+
+ i = start
+ n = 0
+ while n < length:
+ arr[n] = i
+ i += step
+ n += 1
+
+ w_self.w_list = space.newlist([wrapint(space, element)
+ for element in arr])
+ return w_self.w_list
+
+ def getitem(w_self, i):
+ if i < 0:
+ i += w_self.length
+ if i >= w_self.length or i < 0:
+ raise IndexError
+ return w_self.start + i * w_self.step
+
+ def __repr__(w_self):
+ if w_self.w_list is None:
+ return "W_RangeListObject(%s, %s, %s)" % (
+ w_self.start, w_self.step, w_self.length)
+ else:
+ return "W_RangeListObject(%r)" % (w_self.w_list, )
+
+def delegate_range2list(space, w_rangelist):
+ return w_rangelist.force(space)
+
+def len__RangeList(space, w_rangelist):
+ if w_rangelist.w_list is not None:
+ return space.len(w_rangelist.w_list)
+ return wrapint(space, w_rangelist.length)
+
+
+def getitem__RangeList_ANY(space, w_rangelist, w_index):
+ if w_rangelist.w_list is not None:
+ return space.getitem(w_rangelist.w_list, w_index)
+ idx = space.int_w(w_index)
+ try:
+ return w_rangelist.getitem(idx)
+ except IndexError:
+ raise OperationError(space.w_IndexError,
+ space.wrap("list index out of range"))
+
+def getitem__RangeList_Slice(space, w_rangelist, w_slice):
+ if w_rangelist.w_list is not None:
+ return space.getitem(w_rangelist.w_list, w_slice)
+ length = w_rangelist.length
+ start, stop, step, slicelength = w_slice.indices4(space, length)
+ assert slicelength >= 0
+ rangestart = w_rangelist.getitem(start)
+ rangestep = w_rangelist.step * step
+ return W_RangeListObject(rangestart, rangestep, slicelength)
+
+def iter__RangeList(space, w_rangelist):
+ from pypy.objspace.std import iterobject
+ return W_RangeIterObject(w_rangelist)
+
+def repr__RangeList(space, w_rangelist):
+ if w_rangelist.w_list is not None:
+ return space.repr(w_rangelist.w_list)
+ if w_rangelist.length == 0:
+ return space.wrap('[]')
+ result = [''] * w_rangelist.length
+ i = w_rangelist.start
+ n = 0
+ while n < w_rangelist.length:
+ result[n] = str(i)
+ i += w_rangelist.step
+ n += 1
+ return space.wrap("[" + ", ".join(result) + "]")
+
+class W_RangeIterObject(W_Object):
+ from pypy.objspace.std.itertype import iter_typedef as typedef
+
+ def __init__(w_self, w_rangelist, index=0):
+ w_self.w_rangelist = w_rangelist
+ w_self.index = index
+
+def iter__RangeIter(space, w_rangeiter):
+ return w_rangeiter
+
+def next__RangeIter(space, w_rangeiter):
+ if w_rangeiter.w_rangelist is None:
+ raise OperationError(space.w_StopIteration, space.w_None)
+ if w_rangeiter.w_rangelist.w_list is not None:
+ try:
+ w_item = space.getitem(w_rangeiter.w_rangelist.w_list,
+ wrapint(space, w_rangeiter.index))
+ except OperationError, e:
+ w_rangeiter.w_rangelist = None
+ if not e.match(space, space.w_IndexError):
+ raise
+ raise OperationError(space.w_StopIteration, space.w_None)
+ else:
+ try:
+ w_item = wrapint(
+ space,
+ w_rangeiter.w_rangelist.getitem(w_rangeiter.index))
+ except IndexError:
+ w_rangeiter.w_rangelist = None
+ raise OperationError(space.w_StopIteration, space.w_None)
+ w_rangeiter.index += 1
+ return w_item
+
+def len__RangeIter(space, w_rangeiter):
+ if w_rangeiter.w_rangelist is None:
+ return wrapint(space, 0)
+ index = w_rangeiter.index
+ w_length = space.len(w_rangeiter.w_rangelist)
+ w_len = space.sub(w_length, wrapint(space, index))
+ if space.is_true(space.lt(w_len, wrapint(space, 0))):
+ w_len = wrapint(space, 0)
+ return w_len
+
+registerimplementation(W_RangeListObject)
+registerimplementation(W_RangeIterObject)
+
+register_all(vars())
Modified: pypy/dist/pypy/objspace/std/strjoinobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/strjoinobject.py (original)
+++ pypy/dist/pypy/objspace/std/strjoinobject.py Thu Oct 19 19:38:20 2006
@@ -56,6 +56,10 @@
w_self.joined_strs.append(other)
return W_StringJoinObject(w_self.joined_strs)
+#def add__String_StringJoin(space, w_other, w_self):
+# other = space.str_w(w_other)
+# return W_StringObject([other] + w_self.joined_strs)
+
def str__StringJoin(space, w_str):
if type(w_str) is W_StringJoinObject:
return w_str
Added: pypy/dist/pypy/objspace/std/test/test_rangeobject.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/std/test/test_rangeobject.py Thu Oct 19 19:38:20 2006
@@ -0,0 +1,28 @@
+import autopath, py
+
+from pypy.conftest import gettestobjspace
+
+class AppTestRangeListObject(object):
+
+ def setup_class(cls):
+ cls.space = gettestobjspace(**{"objspace.std.withrangelist": True})
+
+ def test_simple(self):
+ result = []
+ for i in range(1, 8, 2):
+ result.append(i)
+ assert result == [1, 3, 5, 7]
+
+ def test_getitem_slice(self):
+ result = []
+ for i in range(1, 100, 2)[40:30:-2]:
+ result.append(i)
+ assert result == [81, 77, 73, 69, 65]
+
+ def test_repr(self):
+ assert repr(range(5)) == "[0, 1, 2, 3, 4]"
+
+ def test_force(self):
+ r = range(10)
+ r[0] = 42
+ assert r == [42, 1, 2, 3, 4, 5, 6, 7, 8, 9]
More information about the Pypy-commit
mailing list