Author: Carl Friedrich Bolz <cfb...@gmx.de>
Branch: list-strategies
Changeset: r47542:97830425eefa
Date: 2011-09-13 11:57 +0200
http://bitbucket.org/pypy/pypy/changeset/97830425eefa/

Log:    add nice XXX to solve

diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -12,6 +12,8 @@
 from pypy.rlib import rerased
 from pypy.interpreter.argument import Signature
 
+# XXX rename cast_*_void_star to erase and unerase
+
 def make_range_list(space, start, step, length):
     if length <= 0:
         strategy = space.fromcache(EmptyListStrategy)
@@ -21,30 +23,23 @@
         storage = strategy.cast_to_void_star((start, step, length))
     return W_ListObject.from_storage_and_strategy(space, storage, strategy)
 
-# don't know where to put this function, so it is global for now
 def get_strategy_from_list_objects(space, list_w):
-    if list_w == []:
+    if not list_w:
         return space.fromcache(EmptyListStrategy)
 
     # check for ints
-    it = iter(list_w)
-    while(True):
-        try:
-            e = it.next()
-            if not is_W_IntObject(e):
-                break
-        except StopIteration:
-            return space.fromcache(IntegerListStrategy)
+    for w_obj in list_w:
+        if not is_W_IntObject(w_obj):
+            break
+    else:
+        return space.fromcache(IntegerListStrategy)
 
     # check for strings
-    it = iter(list_w)
-    while(True):
-        try:
-            e = it.next()
-            if not is_W_StringObject(e):
-                break
-        except StopIteration:
-            return space.fromcache(StringListStrategy)
+    for w_obj in list_w:
+        if not is_W_StringObject(w_obj):
+            break
+    else:
+        return space.fromcache(StringListStrategy)
 
     return space.fromcache(ObjectListStrategy)
 
@@ -56,6 +51,8 @@
     from pypy.objspace.std.stringobject import W_StringObject
     return type(w_object) is W_StringObject
 
+
+
 class W_ListObject(W_Object):
     from pypy.objspace.std.listtype import list_typedef as typedef
 
@@ -63,7 +60,7 @@
         assert isinstance(wrappeditems, list)
         w_self.space = space
         w_self.strategy = get_strategy_from_list_objects(space, wrappeditems)
-        w_self.strategy.init_from_list_w(w_self, wrappeditems)
+        w_self.init_from_list_w(wrappeditems)
 
     @staticmethod
     def from_storage_and_strategy(space, storage, strategy):
@@ -84,11 +81,8 @@
 
     def switch_to_object_strategy(self):
         list_w = self.getitems()
-        strategy = self.strategy = self.space.fromcache(ObjectListStrategy)
-        strategy.init_from_list_w(self, list_w)
-
-    def clone(self):
-        return self.strategy.clone(self)
+        self.strategy = self.space.fromcache(ObjectListStrategy)
+        self.init_from_list_w(list_w)
 
     def _temporarily_as_objects(self):
         if self.strategy is self.space.fromcache(ObjectListStrategy):
@@ -99,9 +93,21 @@
         w_objectlist = W_ListObject.from_storage_and_strategy(self.space, 
storage, strategy)
         return w_objectlist
 
+    # ___________________________________________________
+    # methods that defer to the strategy
+    # XXX add docstrings that explain what the methods do and the requirements
+    # on their arguments (e.g. whether indexes are already positive/range
+    # checked) as well as failure modes
+
+    def init_from_list_w(self, list_w):
+        self.strategy.init_from_list_w(self, list_w)
+
+    def clone(self):
+        return self.strategy.clone(self)
+
     def copy_into(self, other):
+        # XXX what is this used for?
         self.strategy.copy_into(self, other)
-    # ___________________________________________________
 
     def append(w_list, w_item):
         w_list.strategy.append(w_list, w_item)
@@ -130,6 +136,7 @@
         self.strategy.inplace_mul(self, times)
 
     def deleteitem(self, index):
+        # XXX remove the deleteitem method, always use pop
         self.strategy.deleteitem(self, index)
 
     def deleteslice(self, start, step, length):
@@ -228,9 +235,11 @@
         raise NotImplementedError
 
 class EmptyListStrategy(ListStrategy):
+    # XXX add a docstring and say what the storage is
 
     def __init__(self, space):
         ListStrategy.__init__(self, space)
+        # XXX rename to cached_emptylist_w and add a comment what it's used for
         self.emptylist = []
 
     def init_from_list_w(self, w_list, list_w):
@@ -263,9 +272,14 @@
         return self.emptylist
 
     def getstorage_copy(self, w_list):
+        # XXX this is inconsistent with init_from_list_w, where the storage is 
None!
         return self.cast_to_void_star(self.emptylist)
 
     def append(self, w_list, w_item):
+        # XXX this should be done by checking the type of the object directly
+        # here without going through __init__ and
+        # get_strategy_from_list_objects, because it is a very common path.
+        # Compare with EmptyDictStrategy.switch_to_correct_strategy
         w_list.__init__(self.space, [w_item])
 
     def mul(self, w_list, times):
@@ -303,6 +317,7 @@
         pass
 
 class RangeListStrategy(ListStrategy):
+    # XXX add a docstring what the storage looks like
 
     def switch_to_integer_strategy(self, w_list):
         items = self._getitems_range(w_list, False)
@@ -352,12 +367,12 @@
 
     def getitems(self, w_list):
         return self._getitems_range(w_list, True)
+    getitems_copy = getitems
 
     def getstorage_copy(self, w_list):
         # tuple is unmutable
         return w_list.lstorage
 
-    getitems_copy = getitems
 
     @specialize.arg(2)
     def _getitems_range(self, w_list, wrap_items):
@@ -433,6 +448,8 @@
 
     def pop(self, w_list, index):
         l = self.cast_from_void_star(w_list.lstorage)
+        # XXX this is silly: the first if checks whether index == 0 or index
+        # =..., then you do almost the same thing again.
         if index in [0, self.length(w_list)-1]:
             r = self.getitem(w_list, index)
             if index == 0:
@@ -520,12 +537,12 @@
 
     def getitems_copy(self, w_list):
         return [self.wrap(item) for item in 
self.cast_from_void_star(w_list.lstorage)]
+    getitems = getitems_copy
 
     def getstorage_copy(self, w_list):
         items = self.cast_from_void_star(w_list.lstorage)[:]
         return self.cast_to_void_star(items)
 
-    getitems = getitems_copy
 
     def getslice(self, w_list, start, stop, step, length):
         if step == 1 and 0 <= start <= stop:
@@ -592,7 +609,7 @@
         w_list.setitem(index, w_item)
 
     def setslice(self, w_list, start, step, slicelength, w_other):
-        #XXX inefficient
+        #XXX inefficient XXX XXX why?
         assert slicelength >= 0
         items = self.cast_from_void_star(w_list.lstorage)
 
@@ -709,6 +726,7 @@
         return w_item
 
     def mul(self, w_list, times):
+        # XXX can't this be the default implementation in ListStrategy?
         w_newlist = w_list.clone()
         w_newlist.inplace_mul(times)
         return w_newlist
@@ -880,6 +898,7 @@
     start, stop, step, slicelength = w_slice.indices4(space, length)
     assert slicelength >= 0
     if slicelength == 0:
+        # XXX make helper function "new_empty_list" and use it consistently
         strategy = space.fromcache(EmptyListStrategy)
         storage = strategy.cast_to_void_star(None)
         return W_ListObject.from_storage_and_strategy(space, storage, strategy)
@@ -916,6 +935,9 @@
 
 def contains__List_ANY(space, w_list, w_obj):
     # needs to be safe against eq_w() mutating the w_list behind our back
+    # XXX we want to defer that to the list strategy, because it would be a lot
+    # more efficient to not call eq_w on ints. contains is used rather often 
in code like:
+    # if i in [1, 2, 3]: ...
     i = 0
     while i < w_list.length(): # intentionally always calling len!
         if space.eq_w(w_list.getitem(i), w_obj):
@@ -976,8 +998,10 @@
     if w_list1.length() != w_list2.length():
         return space.w_False
 
+    # XXX in theory, this can be implemented more efficiently as well. let's
+    # not care for now
     i = 0
-                                   # is this necessary?
+                                   # is this necessary? XXX yes, it is, 
because eq_w can change any of the two lists. check whether a test for this 
exists!
     while i < w_list1.length() and i < w_list2.length():
         if not space.eq_w(w_list1.getitem(i), w_list2.getitem(i)):
             return space.w_False
@@ -988,6 +1012,8 @@
     # 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
+    # XXX in theory, this can be implemented more efficiently as well. let's
+    # not care for now
     while i < w_list1.length() and i < w_list2.length():
         w_item1 = w_list1.getitem(i)
         w_item2 = w_list2.getitem(i)
@@ -1001,6 +1027,8 @@
     # 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
+    # XXX in theory, this can be implemented more efficiently as well. let's
+    # not care for now
     while i < w_list1.length() and i < w_list2.length():
         w_item1 = w_list1.getitem(i)
         w_item2 = w_list2.getitem(i)
@@ -1110,12 +1138,17 @@
 
 # note that the default value will come back wrapped!!!
 def list_pop__List_ANY(space, w_list, w_idx=-1):
-    if w_list.length() == 0:
+    length = w_list.length()
+    if length == 0:
         raise OperationError(space.w_IndexError,
                              space.wrap("pop from empty list"))
     idx = space.int_w(w_idx)
+    # XXX this shows that the methods on W_ListObject clearly need to say
+    # whether their arguments are index-checked or not. because this is clearly
+    # a bug here: if idx < 0, you add the length. pop will do the same thing
+    # again!
     if idx < 0:
-        idx += w_list.length()
+        idx += length
     try:
         return w_list.pop(idx)
     except IndexError:
@@ -1175,6 +1208,7 @@
         self.w_key = w_key
         self.w_item = w_item
 
+# XXX kill next line? TimSort is already defined above
 TimSort = make_timsort_class()
 # NOTE: all the subclasses of TimSort should inherit from a common subclass,
 #       so make sure that only SimpleSort inherits directly from TimSort.
@@ -1193,6 +1227,7 @@
     def lt(self, a, b):
         return a < b
 
+# XXX kill
 class OldIntSort(SimpleSort):
     def lt(self, w_int1, w_int2):
         from pypy.objspace.std.intobject import W_IntObject
@@ -1201,6 +1236,7 @@
         space = self.space
         return w_int1.intval < w_int2.intval
 
+# XXX kill
 class OldStringSort(SimpleSort):
     def lt(self, w_str1, w_str2):
         from pypy.objspace.std.stringobject import W_StringObject
@@ -1239,6 +1275,7 @@
 def list_sort__List_ANY_ANY_ANY(space, w_list, w_cmp, w_keyfunc, w_reverse):
 
     #XXX so far sorting always wraps list
+    # XXX is this still true?
     has_cmp = not space.is_w(w_cmp, space.w_None)
     has_key = not space.is_w(w_keyfunc, space.w_None)
     has_reverse = space.is_true(w_reverse)
@@ -1253,6 +1290,9 @@
         if has_key:
             sorterclass = CustomKeySort
         else:
+            # XXX this is nonsense. just do something special for the object
+            # strategy and call sort immediately otherwise. implement sort on
+            # the empty list (and the range list, if you want)
             if w_list.strategy is space.fromcache(IntegerListStrategy):
                 w_list.sort(has_reverse)
                 return space.w_None
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to