PageRenderTime 58ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/objspace/std/listobject.py

http://github.com/pypy/pypy
Python | 1552 lines | 1376 code | 105 blank | 71 comment | 29 complexity | 0f15ba5cfb2d5be3f5876af002fc26c3 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. from pypy.objspace.std.model import registerimplementation, W_Object
  2. from pypy.objspace.std.register_all import register_all
  3. from pypy.objspace.std.multimethod import FailedToImplement
  4. from pypy.interpreter.error import OperationError, operationerrfmt
  5. from pypy.objspace.std.inttype import wrapint
  6. from pypy.objspace.std.listtype import get_list_index
  7. from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
  8. from pypy.objspace.std import slicetype
  9. from pypy.interpreter import gateway, baseobjspace
  10. from pypy.rlib.objectmodel import instantiate, specialize, newlist_hint
  11. from pypy.rlib.listsort import make_timsort_class
  12. from pypy.rlib import rerased, jit, debug
  13. from pypy.interpreter.argument import Signature
  14. from pypy.tool.sourcetools import func_with_new_name
  15. UNROLL_CUTOFF = 5
  16. class W_AbstractListObject(W_Object):
  17. __slots__ = ()
  18. def make_range_list(space, start, step, length):
  19. if length <= 0:
  20. strategy = space.fromcache(EmptyListStrategy)
  21. storage = strategy.erase(None)
  22. else:
  23. strategy = space.fromcache(RangeListStrategy)
  24. storage = strategy.erase((start, step, length))
  25. return W_ListObject.from_storage_and_strategy(space, storage, strategy)
  26. def make_empty_list(space):
  27. strategy = space.fromcache(EmptyListStrategy)
  28. storage = strategy.erase(None)
  29. return W_ListObject.from_storage_and_strategy(space, storage, strategy)
  30. @jit.look_inside_iff(lambda space, list_w, sizehint: jit.isconstant(len(list_w)) and len(list_w) < UNROLL_CUTOFF)
  31. def get_strategy_from_list_objects(space, list_w, sizehint):
  32. if not list_w:
  33. if sizehint != -1:
  34. return SizeListStrategy(space, sizehint)
  35. return space.fromcache(EmptyListStrategy)
  36. # check for ints
  37. for w_obj in list_w:
  38. if not is_W_IntObject(w_obj):
  39. break
  40. else:
  41. return space.fromcache(IntegerListStrategy)
  42. # check for strings
  43. for w_obj in list_w:
  44. if not is_W_StringObject(w_obj):
  45. break
  46. else:
  47. return space.fromcache(StringListStrategy)
  48. # check for floats
  49. for w_obj in list_w:
  50. if not is_W_FloatObject(w_obj):
  51. break
  52. else:
  53. return space.fromcache(FloatListStrategy)
  54. return space.fromcache(ObjectListStrategy)
  55. def is_W_IntObject(w_object):
  56. from pypy.objspace.std.intobject import W_IntObject
  57. return type(w_object) is W_IntObject
  58. def is_W_StringObject(w_object):
  59. from pypy.objspace.std.stringobject import W_StringObject
  60. return type(w_object) is W_StringObject
  61. def is_W_FloatObject(w_object):
  62. from pypy.objspace.std.floatobject import W_FloatObject
  63. return type(w_object) is W_FloatObject
  64. class W_ListObject(W_AbstractListObject):
  65. from pypy.objspace.std.listtype import list_typedef as typedef
  66. def __init__(w_self, space, wrappeditems, sizehint=-1):
  67. assert isinstance(wrappeditems, list)
  68. w_self.space = space
  69. if space.config.objspace.std.withliststrategies:
  70. w_self.strategy = get_strategy_from_list_objects(space,
  71. wrappeditems,
  72. sizehint)
  73. else:
  74. w_self.strategy = space.fromcache(ObjectListStrategy)
  75. w_self.init_from_list_w(wrappeditems)
  76. @staticmethod
  77. def from_storage_and_strategy(space, storage, strategy):
  78. w_self = instantiate(W_ListObject)
  79. w_self.space = space
  80. w_self.strategy = strategy
  81. w_self.lstorage = storage
  82. if not space.config.objspace.std.withliststrategies:
  83. w_self.switch_to_object_strategy()
  84. return w_self
  85. @staticmethod
  86. def newlist_str(space, list_s):
  87. strategy = space.fromcache(StringListStrategy)
  88. storage = strategy.erase(list_s)
  89. return W_ListObject.from_storage_and_strategy(space, storage, strategy)
  90. def __repr__(w_self):
  91. """ representation for debugging purposes """
  92. return "%s(%s, %s)" % (w_self.__class__.__name__, w_self.strategy, w_self.lstorage._x)
  93. def unwrap(w_list, space):
  94. # for tests only!
  95. items = [space.unwrap(w_item) for w_item in w_list.getitems()]
  96. return list(items)
  97. def switch_to_object_strategy(self):
  98. if self.strategy is self.space.fromcache(EmptyListStrategy):
  99. list_w = []
  100. else:
  101. list_w = self.getitems()
  102. self.strategy = self.space.fromcache(ObjectListStrategy)
  103. # XXX this is quite indirect
  104. self.init_from_list_w(list_w)
  105. def _temporarily_as_objects(self):
  106. if self.strategy is self.space.fromcache(ObjectListStrategy):
  107. return self
  108. list_w = self.getitems()
  109. strategy = self.space.fromcache(ObjectListStrategy)
  110. storage = strategy.erase(list_w)
  111. w_objectlist = W_ListObject.from_storage_and_strategy(self.space, storage, strategy)
  112. return w_objectlist
  113. # ___________________________________________________
  114. def init_from_list_w(self, list_w):
  115. """Initializes listobject by iterating through the given list of
  116. wrapped items, unwrapping them if neccessary and creating a
  117. new erased object as storage"""
  118. self.strategy.init_from_list_w(self, list_w)
  119. def clear(self, space):
  120. """Initializes (or overrides) the listobject as empty."""
  121. self.space = space
  122. if space.config.objspace.std.withliststrategies:
  123. strategy = space.fromcache(EmptyListStrategy)
  124. else:
  125. strategy = space.fromcache(ObjectListStrategy)
  126. self.strategy = strategy
  127. strategy.clear(self)
  128. def clone(self):
  129. """Returns a clone by creating a new listobject
  130. with the same strategy and a copy of the storage"""
  131. return self.strategy.clone(self)
  132. def copy_into(self, other):
  133. """Used only when extending an EmptyList. Sets the EmptyLists
  134. strategy and storage according to the other W_List"""
  135. self.strategy.copy_into(self, other)
  136. def contains(self, w_obj):
  137. """Returns unwrapped boolean, saying wether w_obj exists
  138. in the list."""
  139. return self.strategy.contains(self, w_obj)
  140. def append(w_list, w_item):
  141. """Appends the wrapped item to the end of the list."""
  142. w_list.strategy.append(w_list, w_item)
  143. def length(self):
  144. return self.strategy.length(self)
  145. def getitem(self, index):
  146. """Returns the wrapped object that is found in the
  147. list at the given index. The index must be unwrapped.
  148. May raise IndexError."""
  149. return self.strategy.getitem(self, index)
  150. def getslice(self, start, stop, step, length):
  151. """Returns a slice of the list defined by the arguments. Arguments must be
  152. normalized (i.e. using normalize_simple_slice or W_Slice.indices4).
  153. May raise IndexError."""
  154. return self.strategy.getslice(self, start, stop, step, length)
  155. def getitems(self):
  156. """Returns a list of all items after wrapping them. The result can
  157. share with the storage, if possible."""
  158. return self.strategy.getitems(self)
  159. def getitems_fixedsize(self):
  160. """Returns a fixed-size list of all items after wrapping them."""
  161. l = self.strategy.getitems_fixedsize(self)
  162. debug.make_sure_not_resized(l)
  163. return l
  164. def getitems_unroll(self):
  165. """Returns a fixed-size list of all items after wrapping them. The JIT
  166. will fully unroll this function. """
  167. l = self.strategy.getitems_unroll(self)
  168. debug.make_sure_not_resized(l)
  169. return l
  170. def getitems_copy(self):
  171. """Returns a copy of all items in the list. Same as getitems except for
  172. ObjectListStrategy."""
  173. return self.strategy.getitems_copy(self)
  174. def getitems_str(self):
  175. """ Return the items in the list as unwrapped strings. If the list does
  176. not use the list strategy, return None. """
  177. return self.strategy.getitems_str(self)
  178. def getitems_int(self):
  179. """ Return the items in the list as unwrapped ints. If the list does
  180. not use the list strategy, return None. """
  181. return self.strategy.getitems_int(self)
  182. # ___________________________________________________
  183. def mul(self, times):
  184. """Returns a copy of the list, multiplied by times.
  185. Argument must be unwrapped."""
  186. return self.strategy.mul(self, times)
  187. def inplace_mul(self, times):
  188. """Alters the list by multiplying its content by times."""
  189. self.strategy.inplace_mul(self, times)
  190. def deleteslice(self, start, step, length):
  191. """Deletes a slice from the list. Used in delitem and delslice.
  192. Arguments must be normalized (see getslice)."""
  193. self.strategy.deleteslice(self, start, step, length)
  194. def pop(self, index):
  195. """Pops an item from the list. Index must be normalized.
  196. May raise IndexError."""
  197. return self.strategy.pop(self, index)
  198. def pop_end(self):
  199. """ Pop the last element from the list."""
  200. return self.strategy.pop_end(self)
  201. def setitem(self, index, w_item):
  202. """Inserts a wrapped item at the given (unwrapped) index.
  203. May raise IndexError."""
  204. self.strategy.setitem(self, index, w_item)
  205. def setslice(self, start, step, slicelength, sequence_w):
  206. """Sets the slice of the list from start to start+step*slicelength to
  207. the sequence sequence_w.
  208. Used by setslice and setitem."""
  209. self.strategy.setslice(self, start, step, slicelength, sequence_w)
  210. def insert(self, index, w_item):
  211. """Inserts an item at the given position. Item must be wrapped,
  212. index not."""
  213. self.strategy.insert(self, index, w_item)
  214. def extend(self, items_w):
  215. """Appends the given list of wrapped items."""
  216. self.strategy.extend(self, items_w)
  217. def reverse(self):
  218. """Reverses the list."""
  219. self.strategy.reverse(self)
  220. def sort(self, reverse):
  221. """Sorts the list ascending or descending depending on
  222. argument reverse. Argument must be unwrapped."""
  223. self.strategy.sort(self, reverse)
  224. registerimplementation(W_ListObject)
  225. class ListStrategy(object):
  226. sizehint = -1
  227. def __init__(self, space):
  228. self.space = space
  229. def init_from_list_w(self, w_list, list_w):
  230. raise NotImplementedError
  231. def clone(self, w_list):
  232. raise NotImplementedError
  233. def copy_into(self, w_list, w_other):
  234. raise NotImplementedError
  235. def contains(self, w_list, w_obj):
  236. # needs to be safe against eq_w() mutating the w_list behind our back
  237. i = 0
  238. while i < w_list.length(): # intentionally always calling len!
  239. if self.space.eq_w(w_list.getitem(i), w_obj):
  240. return True
  241. i += 1
  242. return False
  243. def length(self, w_list):
  244. raise NotImplementedError
  245. def getitem(self, w_list, index):
  246. raise NotImplementedError
  247. def getslice(self, w_list, start, stop, step, length):
  248. raise NotImplementedError
  249. def getitems(self, w_list):
  250. return self.getitems_copy(w_list)
  251. def getitems_copy(self, w_list):
  252. raise NotImplementedError
  253. def getitems_str(self, w_list):
  254. return None
  255. def getitems_int(self, w_list):
  256. return None
  257. def getstorage_copy(self, w_list):
  258. raise NotImplementedError
  259. def append(self, w_list, w_item):
  260. raise NotImplementedError
  261. def mul(self, w_list, times):
  262. w_newlist = w_list.clone()
  263. w_newlist.inplace_mul(times)
  264. return w_newlist
  265. def inplace_mul(self, w_list, times):
  266. raise NotImplementedError
  267. def deleteslice(self, w_list, start, step, slicelength):
  268. raise NotImplementedError
  269. def pop(self, w_list, index):
  270. raise NotImplementedError
  271. def pop_end(self, w_list):
  272. return self.pop(w_list, self.length(w_list) - 1)
  273. def setitem(self, w_list, index, w_item):
  274. raise NotImplementedError
  275. def setslice(self, w_list, start, step, slicelength, sequence_w):
  276. raise NotImplementedError
  277. def insert(self, w_list, index, w_item):
  278. raise NotImplementedError
  279. def extend(self, w_list, items_w):
  280. raise NotImplementedError
  281. def reverse(self, w_list):
  282. raise NotImplementedError
  283. def sort(self, w_list, reverse):
  284. raise NotImplementedError
  285. class EmptyListStrategy(ListStrategy):
  286. """EmptyListStrategy is used when a W_List withouth elements is created.
  287. The storage is None. When items are added to the W_List a new RPython list
  288. is created and the strategy and storage of the W_List are changed depending
  289. to the added item.
  290. W_Lists do not switch back to EmptyListStrategy when becoming empty again."""
  291. _applevel_repr = "empty"
  292. def __init__(self, space):
  293. ListStrategy.__init__(self, space)
  294. def init_from_list_w(self, w_list, list_w):
  295. assert len(list_w) == 0
  296. w_list.lstorage = self.erase(None)
  297. def clear(self, w_list):
  298. w_list.lstorage = self.erase(None)
  299. erase, unerase = rerased.new_erasing_pair("empty")
  300. erase = staticmethod(erase)
  301. unerase = staticmethod(unerase)
  302. def clone(self, w_list):
  303. return W_ListObject.from_storage_and_strategy(self.space, w_list.lstorage, self)
  304. def copy_into(self, w_list, w_other):
  305. pass
  306. def contains(self, w_list, w_obj):
  307. return False
  308. def length(self, w_list):
  309. return 0
  310. def getitem(self, w_list, index):
  311. raise IndexError
  312. def getslice(self, w_list, start, stop, step, length):
  313. # will never be called because the empty list case is already caught in
  314. # getslice__List_ANY_ANY and getitem__List_Slice
  315. return W_ListObject(self.space, [])
  316. def getitems(self, w_list):
  317. return []
  318. def getitems_copy(self, w_list):
  319. return []
  320. getitems_fixedsize = func_with_new_name(getitems_copy, "getitems_fixedsize")
  321. getitems_unroll = getitems_fixedsize
  322. def getstorage_copy(self, w_list):
  323. return self.erase(None)
  324. def switch_to_correct_strategy(self, w_list, w_item):
  325. if is_W_IntObject(w_item):
  326. strategy = self.space.fromcache(IntegerListStrategy)
  327. elif is_W_StringObject(w_item):
  328. strategy = self.space.fromcache(StringListStrategy)
  329. elif is_W_FloatObject(w_item):
  330. strategy = self.space.fromcache(FloatListStrategy)
  331. else:
  332. strategy = self.space.fromcache(ObjectListStrategy)
  333. storage = strategy.get_empty_storage(self.sizehint)
  334. w_list.strategy = strategy
  335. w_list.lstorage = storage
  336. def append(self, w_list, w_item):
  337. self.switch_to_correct_strategy(w_list, w_item)
  338. w_list.append(w_item)
  339. def inplace_mul(self, w_list, times):
  340. return
  341. def deleteslice(self, w_list, start, step, slicelength):
  342. pass
  343. def pop(self, w_list, index):
  344. # will not be called because IndexError was already raised in
  345. # list_pop__List_ANY
  346. raise IndexError
  347. def setitem(self, w_list, index, w_item):
  348. raise IndexError
  349. def setslice(self, w_list, start, step, slicelength, w_other):
  350. strategy = w_other.strategy
  351. storage = strategy.getstorage_copy(w_other)
  352. w_list.strategy = strategy
  353. w_list.lstorage = storage
  354. def sort(self, w_list, reverse):
  355. return
  356. def insert(self, w_list, index, w_item):
  357. assert index == 0
  358. self.append(w_list, w_item)
  359. def extend(self, w_list, w_other):
  360. w_other.copy_into(w_list)
  361. def reverse(self, w_list):
  362. pass
  363. class SizeListStrategy(EmptyListStrategy):
  364. """ Like empty, but when modified it'll preallocate the size to sizehint
  365. """
  366. def __init__(self, space, sizehint):
  367. self.sizehint = sizehint
  368. ListStrategy.__init__(self, space)
  369. class RangeListStrategy(ListStrategy):
  370. """RangeListStrategy is used when a list is created using the range method.
  371. The storage is a tuple containing only three integers start, step and length
  372. and elements are calculated based on these values.
  373. On any operation destroying the range (inserting, appending non-ints)
  374. the strategy is switched to IntegerListStrategy."""
  375. _applevel_repr = "range"
  376. def switch_to_integer_strategy(self, w_list):
  377. items = self._getitems_range(w_list, False)
  378. strategy = w_list.strategy = self.space.fromcache(IntegerListStrategy)
  379. w_list.lstorage = strategy.erase(items)
  380. def wrap(self, intval):
  381. return self.space.wrap(intval)
  382. def unwrap(self, w_int):
  383. return self.space.int_w(w_int)
  384. def init_from_list_w(self, w_list, list_w):
  385. raise NotImplementedError
  386. erase, unerase = rerased.new_erasing_pair("range")
  387. erase = staticmethod(erase)
  388. unerase = staticmethod(unerase)
  389. def clone(self, w_list):
  390. storage = w_list.lstorage # lstorage is tuple, no need to clone
  391. w_clone = W_ListObject.from_storage_and_strategy(self.space, storage, self)
  392. return w_clone
  393. def copy_into(self, w_list, w_other):
  394. w_other.strategy = self
  395. w_other.lstorage = w_list.lstorage
  396. def contains(self, w_list, w_obj):
  397. if is_W_IntObject(w_obj):
  398. start, step, length = self.unerase(w_list.lstorage)
  399. obj = self.unwrap(w_obj)
  400. i = start
  401. if step > 0 and start <= obj <= start + (length - 1) * step and (start - obj) % step == 0:
  402. return True
  403. elif step < 0 and start + (length -1) * step <= obj <= start and (start - obj) % step == 0:
  404. return True
  405. else:
  406. return False
  407. return ListStrategy.contains(self, w_list, w_obj)
  408. def length(self, w_list):
  409. return self.unerase(w_list.lstorage)[2]
  410. def _getitem_unwrapped(self, w_list, i):
  411. v = self.unerase(w_list.lstorage)
  412. start = v[0]
  413. step = v[1]
  414. length = v[2]
  415. if i < 0:
  416. i += length
  417. if i < 0:
  418. raise IndexError
  419. elif i >= length:
  420. raise IndexError
  421. return start + i * step
  422. def getitems_int(self, w_list):
  423. return self._getitems_range(w_list, False)
  424. def getitem(self, w_list, i):
  425. return self.wrap(self._getitem_unwrapped(w_list, i))
  426. def getitems_copy(self, w_list):
  427. return self._getitems_range(w_list, True)
  428. def getstorage_copy(self, w_list):
  429. # tuple is unmutable
  430. return w_list.lstorage
  431. @specialize.arg(2)
  432. def _getitems_range(self, w_list, wrap_items):
  433. l = self.unerase(w_list.lstorage)
  434. start = l[0]
  435. step = l[1]
  436. length = l[2]
  437. if wrap_items:
  438. r = [None] * length
  439. else:
  440. r = [0] * length
  441. i = start
  442. n = 0
  443. while n < length:
  444. if wrap_items:
  445. r[n] = self.wrap(i)
  446. else:
  447. r[n] = i
  448. i += step
  449. n += 1
  450. return r
  451. @jit.dont_look_inside
  452. def getitems_fixedsize(self, w_list):
  453. return self._getitems_range_unroll(w_list, True)
  454. def getitems_unroll(self, w_list):
  455. return self._getitems_range_unroll(w_list, True)
  456. _getitems_range_unroll = jit.unroll_safe(func_with_new_name(_getitems_range, "_getitems_range_unroll"))
  457. def getslice(self, w_list, start, stop, step, length):
  458. v = self.unerase(w_list.lstorage)
  459. old_start = v[0]
  460. old_step = v[1]
  461. old_length = v[2]
  462. new_start = self._getitem_unwrapped(w_list, start)
  463. new_step = old_step * step
  464. return make_range_list(self.space, new_start, new_step, length)
  465. def append(self, w_list, w_item):
  466. if is_W_IntObject(w_item):
  467. l = self.unerase(w_list.lstorage)
  468. step = l[1]
  469. last_in_range = self._getitem_unwrapped(w_list, -1)
  470. if self.unwrap(w_item) - step == last_in_range:
  471. new = self.erase((l[0],l[1],l[2]+1))
  472. w_list.lstorage = new
  473. return
  474. self.switch_to_integer_strategy(w_list)
  475. else:
  476. w_list.switch_to_object_strategy()
  477. w_list.append(w_item)
  478. def inplace_mul(self, w_list, times):
  479. self.switch_to_integer_strategy(w_list)
  480. w_list.inplace_mul(times)
  481. def deleteslice(self, w_list, start, step, slicelength):
  482. self.switch_to_integer_strategy(w_list)
  483. w_list.deleteslice(start, step, slicelength)
  484. def pop_end(self, w_list):
  485. start, step, length = self.unerase(w_list.lstorage)
  486. w_result = self.wrap(start + (length - 1) * step)
  487. new = self.erase((start, step, length - 1))
  488. w_list.lstorage = new
  489. return w_result
  490. def pop(self, w_list, index):
  491. l = self.unerase(w_list.lstorage)
  492. start = l[0]
  493. step = l[1]
  494. length = l[2]
  495. if index == 0:
  496. w_result = self.wrap(start)
  497. new = self.erase((start + step, step, length - 1))
  498. w_list.lstorage = new
  499. return w_result
  500. elif index == length - 1:
  501. return self.pop_end(w_list)
  502. else:
  503. self.switch_to_integer_strategy(w_list)
  504. return w_list.pop(index)
  505. def setitem(self, w_list, index, w_item):
  506. self.switch_to_integer_strategy(w_list)
  507. w_list.setitem(index, w_item)
  508. def setslice(self, w_list, start, step, slicelength, sequence_w):
  509. self.switch_to_integer_strategy(w_list)
  510. w_list.setslice(start, step, slicelength, sequence_w)
  511. def sort(self, w_list, reverse):
  512. start, step, length = self.unerase(w_list.lstorage)
  513. if step > 0 and reverse or step < 0 and not reverse:
  514. start = start + step * (length - 1)
  515. step = step * (-1)
  516. else:
  517. return
  518. w_list.lstorage = self.erase((start, step, length))
  519. def insert(self, w_list, index, w_item):
  520. self.switch_to_integer_strategy(w_list)
  521. w_list.insert(index, w_item)
  522. def extend(self, w_list, items_w):
  523. self.switch_to_integer_strategy(w_list)
  524. w_list.extend(items_w)
  525. def reverse(self, w_list):
  526. v = self.unerase(w_list.lstorage)
  527. last = self._getitem_unwrapped(w_list, -1)
  528. length = v[2]
  529. skip = v[1]
  530. new = self.erase((last, -skip, length))
  531. w_list.lstorage = new
  532. class AbstractUnwrappedStrategy(object):
  533. _mixin_ = True
  534. def wrap(self, unwrapped):
  535. raise NotImplementedError
  536. def unwrap(self, wrapped):
  537. raise NotImplementedError
  538. @staticmethod
  539. def unerase(storage):
  540. raise NotImplementedError("abstract base class")
  541. @staticmethod
  542. def erase(obj):
  543. raise NotImplementedError("abstract base class")
  544. def is_correct_type(self, w_obj):
  545. raise NotImplementedError("abstract base class")
  546. def list_is_correct_type(self, w_list):
  547. raise NotImplementedError("abstract base class")
  548. @jit.look_inside_iff(lambda space, w_list, list_w:
  549. jit.isconstant(len(list_w)) and len(list_w) < UNROLL_CUTOFF)
  550. def init_from_list_w(self, w_list, list_w):
  551. l = [self.unwrap(w_item) for w_item in list_w]
  552. w_list.lstorage = self.erase(l)
  553. def get_empty_storage(self, sizehint):
  554. if sizehint == -1:
  555. return self.erase([])
  556. return self.erase(newlist_hint(sizehint))
  557. def clone(self, w_list):
  558. l = self.unerase(w_list.lstorage)
  559. storage = self.erase(l[:])
  560. w_clone = W_ListObject.from_storage_and_strategy(self.space, storage, self)
  561. return w_clone
  562. def copy_into(self, w_list, w_other):
  563. w_other.strategy = self
  564. items = self.unerase(w_list.lstorage)[:]
  565. w_other.lstorage = self.erase(items)
  566. def contains(self, w_list, w_obj):
  567. if self.is_correct_type(w_obj):
  568. obj = self.unwrap(w_obj)
  569. l = self.unerase(w_list.lstorage)
  570. for i in l:
  571. if i == obj:
  572. return True
  573. return False
  574. return ListStrategy.contains(self, w_list, w_obj)
  575. def length(self, w_list):
  576. return len(self.unerase(w_list.lstorage))
  577. def getitem(self, w_list, index):
  578. l = self.unerase(w_list.lstorage)
  579. try:
  580. r = l[index]
  581. except IndexError: # make RPython raise the exception
  582. raise
  583. return self.wrap(r)
  584. @jit.look_inside_iff(lambda self, w_list:
  585. jit.isconstant(w_list.length()) and w_list.length() < UNROLL_CUTOFF)
  586. def getitems_copy(self, w_list):
  587. return [self.wrap(item) for item in self.unerase(w_list.lstorage)]
  588. @jit.unroll_safe
  589. def getitems_unroll(self, w_list):
  590. return [self.wrap(item) for item in self.unerase(w_list.lstorage)]
  591. @jit.look_inside_iff(lambda self, w_list:
  592. jit.isconstant(w_list.length()) and w_list.length() < UNROLL_CUTOFF)
  593. def getitems_fixedsize(self, w_list):
  594. return self.getitems_unroll(w_list)
  595. def getstorage_copy(self, w_list):
  596. items = self.unerase(w_list.lstorage)[:]
  597. return self.erase(items)
  598. def getslice(self, w_list, start, stop, step, length):
  599. if step == 1 and 0 <= start <= stop:
  600. l = self.unerase(w_list.lstorage)
  601. assert start >= 0
  602. assert stop >= 0
  603. sublist = l[start:stop]
  604. storage = self.erase(sublist)
  605. return W_ListObject.from_storage_and_strategy(self.space, storage, self)
  606. else:
  607. subitems_w = [self._none_value] * length
  608. l = self.unerase(w_list.lstorage)
  609. for i in range(length):
  610. try:
  611. subitems_w[i] = l[start]
  612. start += step
  613. except IndexError:
  614. raise
  615. storage = self.erase(subitems_w)
  616. return W_ListObject.from_storage_and_strategy(self.space, storage, self)
  617. def append(self, w_list, w_item):
  618. if self.is_correct_type(w_item):
  619. self.unerase(w_list.lstorage).append(self.unwrap(w_item))
  620. return
  621. w_list.switch_to_object_strategy()
  622. w_list.append(w_item)
  623. def insert(self, w_list, index, w_item):
  624. l = self.unerase(w_list.lstorage)
  625. if self.is_correct_type(w_item):
  626. l.insert(index, self.unwrap(w_item))
  627. return
  628. w_list.switch_to_object_strategy()
  629. w_list.insert(index, w_item)
  630. def extend(self, w_list, w_other):
  631. l = self.unerase(w_list.lstorage)
  632. if self.list_is_correct_type(w_other):
  633. l += self.unerase(w_other.lstorage)
  634. return
  635. elif w_other.strategy is self.space.fromcache(EmptyListStrategy):
  636. return
  637. w_other = w_other._temporarily_as_objects()
  638. w_list.switch_to_object_strategy()
  639. w_list.extend(w_other)
  640. def setitem(self, w_list, index, w_item):
  641. l = self.unerase(w_list.lstorage)
  642. if self.is_correct_type(w_item):
  643. try:
  644. l[index] = self.unwrap(w_item)
  645. except IndexError:
  646. raise
  647. return
  648. w_list.switch_to_object_strategy()
  649. w_list.setitem(index, w_item)
  650. def setslice(self, w_list, start, step, slicelength, w_other):
  651. assert slicelength >= 0
  652. items = self.unerase(w_list.lstorage)
  653. if self is self.space.fromcache(ObjectListStrategy):
  654. w_other = w_other._temporarily_as_objects()
  655. elif (not self.list_is_correct_type(w_other) and
  656. w_other.length() != 0):
  657. w_list.switch_to_object_strategy()
  658. w_other_as_object = w_other._temporarily_as_objects()
  659. assert w_other_as_object.strategy is self.space.fromcache(ObjectListStrategy)
  660. w_list.setslice(start, step, slicelength, w_other_as_object)
  661. return
  662. oldsize = len(items)
  663. len2 = w_other.length()
  664. if step == 1: # Support list resizing for non-extended slices
  665. delta = slicelength - len2
  666. if delta < 0:
  667. delta = -delta
  668. newsize = oldsize + delta
  669. # XXX support this in rlist!
  670. items += [self._none_value] * delta
  671. lim = start+len2
  672. i = newsize - 1
  673. while i >= lim:
  674. items[i] = items[i-delta]
  675. i -= 1
  676. elif delta == 0:
  677. pass
  678. else:
  679. assert start >= 0 # start<0 is only possible with slicelength==0
  680. del items[start:start+delta]
  681. elif len2 != slicelength: # No resize for extended slices
  682. raise operationerrfmt(self.space.w_ValueError, "attempt to "
  683. "assign sequence of size %d to extended slice of size %d",
  684. len2, slicelength)
  685. if w_other.strategy is self.space.fromcache(EmptyListStrategy):
  686. other_items = []
  687. else:
  688. # at this point both w_list and w_other have the same type, so
  689. # self.unerase is valid for both of them
  690. other_items = self.unerase(w_other.lstorage)
  691. if other_items is items:
  692. if step > 0:
  693. # Always copy starting from the right to avoid
  694. # having to make a shallow copy in the case where
  695. # the source and destination lists are the same list.
  696. i = len2 - 1
  697. start += i*step
  698. while i >= 0:
  699. items[start] = other_items[i]
  700. start -= step
  701. i -= 1
  702. return
  703. else:
  704. # Make a shallow copy to more easily handle the reversal case
  705. w_list.reverse()
  706. return
  707. #other_items = list(other_items)
  708. for i in range(len2):
  709. items[start] = other_items[i]
  710. start += step
  711. def deleteslice(self, w_list, start, step, slicelength):
  712. items = self.unerase(w_list.lstorage)
  713. if slicelength==0:
  714. return
  715. if step < 0:
  716. start = start + step * (slicelength-1)
  717. step = -step
  718. if step == 1:
  719. assert start >= 0
  720. if slicelength > 0:
  721. del items[start:start+slicelength]
  722. else:
  723. n = len(items)
  724. i = start
  725. for discard in range(1, slicelength):
  726. j = i+1
  727. i += step
  728. while j < i:
  729. items[j-discard] = items[j]
  730. j += 1
  731. j = i+1
  732. while j < n:
  733. items[j-slicelength] = items[j]
  734. j += 1
  735. start = n - slicelength
  736. assert start >= 0 # annotator hint
  737. del items[start:]
  738. def pop_end(self, w_list):
  739. l = self.unerase(w_list.lstorage)
  740. return self.wrap(l.pop())
  741. def pop(self, w_list, index):
  742. l = self.unerase(w_list.lstorage)
  743. # not sure if RPython raises IndexError on pop
  744. # so check again here
  745. if index < 0:
  746. raise IndexError
  747. try:
  748. item = l.pop(index)
  749. except IndexError:
  750. raise
  751. w_item = self.wrap(item)
  752. return w_item
  753. def inplace_mul(self, w_list, times):
  754. l = self.unerase(w_list.lstorage)
  755. l *= times
  756. def reverse(self, w_list):
  757. self.unerase(w_list.lstorage).reverse()
  758. class ObjectListStrategy(AbstractUnwrappedStrategy, ListStrategy):
  759. _none_value = None
  760. _applevel_repr = "object"
  761. def unwrap(self, w_obj):
  762. return w_obj
  763. def wrap(self, item):
  764. return item
  765. erase, unerase = rerased.new_erasing_pair("object")
  766. erase = staticmethod(erase)
  767. unerase = staticmethod(unerase)
  768. def is_correct_type(self, w_obj):
  769. return True
  770. def list_is_correct_type(self, w_list):
  771. return w_list.strategy is self.space.fromcache(ObjectListStrategy)
  772. def init_from_list_w(self, w_list, list_w):
  773. w_list.lstorage = self.erase(list_w)
  774. def clear(self, w_list):
  775. w_list.lstorage = self.erase([])
  776. def contains(self, w_list, w_obj):
  777. return ListStrategy.contains(self, w_list, w_obj)
  778. def getitems(self, w_list):
  779. return self.unerase(w_list.lstorage)
  780. class IntegerListStrategy(AbstractUnwrappedStrategy, ListStrategy):
  781. _none_value = 0
  782. _applevel_repr = "int"
  783. def wrap(self, intval):
  784. return self.space.wrap(intval)
  785. def unwrap(self, w_int):
  786. return self.space.int_w(w_int)
  787. erase, unerase = rerased.new_erasing_pair("integer")
  788. erase = staticmethod(erase)
  789. unerase = staticmethod(unerase)
  790. def is_correct_type(self, w_obj):
  791. return is_W_IntObject(w_obj)
  792. def list_is_correct_type(self, w_list):
  793. return w_list.strategy is self.space.fromcache(IntegerListStrategy)
  794. def sort(self, w_list, reverse):
  795. l = self.unerase(w_list.lstorage)
  796. sorter = IntSort(l, len(l))
  797. sorter.sort()
  798. if reverse:
  799. l.reverse()
  800. def getitems_int(self, w_list):
  801. return self.unerase(w_list.lstorage)
  802. class FloatListStrategy(AbstractUnwrappedStrategy, ListStrategy):
  803. _none_value = 0.0
  804. _applevel_repr = "float"
  805. def wrap(self, floatval):
  806. return self.space.wrap(floatval)
  807. def unwrap(self, w_float):
  808. return self.space.float_w(w_float)
  809. erase, unerase = rerased.new_erasing_pair("float")
  810. erase = staticmethod(erase)
  811. unerase = staticmethod(unerase)
  812. def is_correct_type(self, w_obj):
  813. return is_W_FloatObject(w_obj)
  814. def list_is_correct_type(self, w_list):
  815. return w_list.strategy is self.space.fromcache(FloatListStrategy)
  816. def sort(self, w_list, reverse):
  817. l = self.unerase(w_list.lstorage)
  818. sorter = FloatSort(l, len(l))
  819. sorter.sort()
  820. if reverse:
  821. l.reverse()
  822. class StringListStrategy(AbstractUnwrappedStrategy, ListStrategy):
  823. _none_value = None
  824. _applevel_repr = "str"
  825. def wrap(self, stringval):
  826. return self.space.wrap(stringval)
  827. def unwrap(self, w_string):
  828. return self.space.str_w(w_string)
  829. erase, unerase = rerased.new_erasing_pair("string")
  830. erase = staticmethod(erase)
  831. unerase = staticmethod(unerase)
  832. def is_correct_type(self, w_obj):
  833. return is_W_StringObject(w_obj)
  834. def list_is_correct_type(self, w_list):
  835. return w_list.strategy is self.space.fromcache(StringListStrategy)
  836. def sort(self, w_list, reverse):
  837. l = self.unerase(w_list.lstorage)
  838. sorter = StringSort(l, len(l))
  839. sorter.sort()
  840. if reverse:
  841. l.reverse()
  842. def getitems_str(self, w_list):
  843. return self.unerase(w_list.lstorage)
  844. # _______________________________________________________
  845. init_signature = Signature(['sequence'], None, None)
  846. init_defaults = [None]
  847. def init__List(space, w_list, __args__):
  848. from pypy.objspace.std.tupleobject import W_AbstractTupleObject
  849. # this is on the silly side
  850. w_iterable, = __args__.parse_obj(
  851. None, 'list', init_signature, init_defaults)
  852. w_list.clear(space)
  853. if w_iterable is not None:
  854. if type(w_iterable) is W_ListObject:
  855. w_iterable.copy_into(w_list)
  856. return
  857. elif isinstance(w_iterable, W_AbstractTupleObject):
  858. w_list.__init__(space, w_iterable.getitems_copy())
  859. return
  860. intlist = space.listview_int(w_iterable)
  861. if intlist is not None:
  862. w_list.strategy = strategy = space.fromcache(IntegerListStrategy)
  863. # need to copy because intlist can share with w_iterable
  864. w_list.lstorage = strategy.erase(intlist[:])
  865. return
  866. strlist = space.listview_str(w_iterable)
  867. if strlist is not None:
  868. w_list.strategy = strategy = space.fromcache(StringListStrategy)
  869. # need to copy because intlist can share with w_iterable
  870. w_list.lstorage = strategy.erase(strlist[:])
  871. return
  872. # xxx special hack for speed
  873. from pypy.interpreter.generator import GeneratorIterator
  874. if isinstance(w_iterable, GeneratorIterator):
  875. w_iterable.unpack_into_w(w_list)
  876. return
  877. # /xxx
  878. _init_from_iterable(space, w_list, w_iterable)
  879. def _init_from_iterable(space, w_list, w_iterable):
  880. # in its own function to make the JIT look into init__List
  881. w_iterator = space.iter(w_iterable)
  882. while True:
  883. try:
  884. w_item = space.next(w_iterator)
  885. except OperationError, e:
  886. if not e.match(space, space.w_StopIteration):
  887. raise
  888. break # done
  889. w_list.append(w_item)
  890. def len__List(space, w_list):
  891. result = w_list.length()
  892. return wrapint(space, result)
  893. def getitem__List_ANY(space, w_list, w_index):
  894. try:
  895. return w_list.getitem(get_list_index(space, w_index))
  896. except IndexError:
  897. raise OperationError(space.w_IndexError,
  898. space.wrap("list index out of range"))
  899. def getitem__List_Slice(space, w_list, w_slice):
  900. # XXX consider to extend rlist's functionality?
  901. length = w_list.length()
  902. start, stop, step, slicelength = w_slice.indices4(space, length)
  903. assert slicelength >= 0
  904. if slicelength == 0:
  905. return make_empty_list(space)
  906. return w_list.getslice(start, stop, step, slicelength)
  907. def getslice__List_ANY_ANY(space, w_list, w_start, w_stop):
  908. length = w_list.length()
  909. start, stop = normalize_simple_slice(space, length, w_start, w_stop)
  910. slicelength = stop - start
  911. if slicelength == 0:
  912. return make_empty_list(space)
  913. return w_list.getslice(start, stop, 1, stop - start)
  914. def setslice__List_ANY_ANY_List(space, w_list, w_start, w_stop, w_other):
  915. length = w_list.length()
  916. start, stop = normalize_simple_slice(space, length, w_start, w_stop)
  917. w_list.setslice(start, 1, stop-start, w_other)
  918. def setslice__List_ANY_ANY_ANY(space, w_list, w_start, w_stop, w_iterable):
  919. length = w_list.length()
  920. start, stop = normalize_simple_slice(space, length, w_start, w_stop)
  921. sequence_w = space.listview(w_iterable)
  922. w_other = W_ListObject(space, sequence_w)
  923. w_list.setslice(start, 1, stop-start, w_other)
  924. def delslice__List_ANY_ANY(space, w_list, w_start, w_stop):
  925. length = w_list.length()
  926. start, stop = normalize_simple_slice(space, length, w_start, w_stop)
  927. w_list.deleteslice(start, 1, stop-start)
  928. def contains__List_ANY(space, w_list, w_obj):
  929. return space.wrap(w_list.contains(w_obj))
  930. def iter__List(space, w_list):
  931. from pypy.objspace.std import iterobject
  932. return iterobject.W_FastListIterObject(w_list)
  933. def add__List_List(space, w_list1, w_list2):
  934. w_clone = w_list1.clone()
  935. w_clone.extend(w_list2)
  936. return w_clone
  937. def inplace_add__List_ANY(space, w_list1, w_iterable2):
  938. try:
  939. list_extend__List_ANY(space, w_list1, w_iterable2)
  940. except OperationError, e:
  941. if e.match(space, space.w_TypeError):
  942. raise FailedToImplement
  943. raise
  944. return w_list1
  945. def inplace_add__List_List(space, w_list1, w_list2):
  946. list_extend__List_List(space, w_list1, w_list2)
  947. return w_list1
  948. def mul_list_times(space, w_list, w_times):
  949. try:
  950. times = space.getindex_w(w_times, space.w_OverflowError)
  951. except OperationError, e:
  952. if e.match(space, space.w_TypeError):
  953. raise FailedToImplement
  954. raise
  955. return w_list.mul(times)
  956. def mul__List_ANY(space, w_list, w_times):
  957. return mul_list_times(space, w_list, w_times)
  958. def mul__ANY_List(space, w_times, w_list):
  959. return mul_list_times(space, w_list, w_times)
  960. def inplace_mul__List_ANY(space, w_list, w_times):
  961. try:
  962. times = space.getindex_w(w_times, space.w_OverflowError)
  963. except OperationError, e:
  964. if e.match(space, space.w_TypeError):
  965. raise FailedToImplement
  966. raise
  967. w_list.inplace_mul(times)
  968. return w_list
  969. def eq__List_List(space, w_list1, w_list2):
  970. # needs to be safe against eq_w() mutating the w_lists behind our back
  971. if w_list1.length() != w_list2.length():
  972. return space.w_False
  973. # XXX in theory, this can be implemented more efficiently as well. let's
  974. # not care for now
  975. i = 0
  976. while i < w_list1.length() and i < w_list2.length():
  977. if not space.eq_w(w_list1.getitem(i), w_list2.getitem(i)):
  978. return space.w_False
  979. i += 1
  980. return space.w_True
  981. def lessthan_unwrappeditems(space, w_list1, w_list2):
  982. # needs to be safe against eq_w() mutating the w_lists behind our back
  983. # Search for the first index where items are different
  984. i = 0
  985. # XXX in theory, this can be implemented more efficiently as well. let's
  986. # not care for now
  987. while i < w_list1.length() and i < w_list2.length():
  988. w_item1 = w_list1.getitem(i)
  989. w_item2 = w_list2.getitem(i)
  990. if not space.eq_w(w_item1, w_item2):
  991. return space.lt(w_item1, w_item2)
  992. i += 1
  993. # No more items to compare -- compare sizes
  994. return space.newbool(w_list1.length() < w_list2.length())
  995. def greaterthan_unwrappeditems(space, w_list1, w_list2):
  996. # needs to be safe against eq_w() mutating the w_lists behind our back
  997. # Search for the first index where items are different
  998. i = 0
  999. # XXX in theory, this can be implemented more efficiently as well. let's
  1000. # not care for now
  1001. while i < w_list1.length() and i < w_list2.length():
  1002. w_item1 = w_list1.getitem(i)
  1003. w_item2 = w_list2.getitem(i)
  1004. if not space.eq_w(w_item1, w_item2):
  1005. return space.gt(w_item1, w_item2)
  1006. i += 1
  1007. # No more items to compare -- compare sizes
  1008. return space.newbool(w_list1.length() > w_list2.length())
  1009. def lt__List_List(space, w_list1, w_list2):
  1010. return lessthan_unwrappeditems(space, w_list1, w_list2)
  1011. def gt__List_List(space, w_list1, w_list2):
  1012. return greaterthan_unwrappeditems(space, w_list1, w_list2)
  1013. def delitem__List_ANY(space, w_list, w_idx):
  1014. idx = get_list_index(space, w_idx)
  1015. if idx < 0:
  1016. idx += w_list.length()
  1017. try:
  1018. w_list.pop(idx)
  1019. except IndexError:
  1020. raise OperationError(space.w_IndexError,
  1021. space.wrap("list deletion index out of range"))
  1022. return space.w_None
  1023. def delitem__List_Slice(space, w_list, w_slice):
  1024. start, stop, step, slicelength = w_slice.indices4(space, w_list.length())
  1025. w_list.deleteslice(start, step, slicelength)
  1026. def setitem__List_ANY_ANY(space, w_list, w_index, w_any):
  1027. idx = get_list_index(space, w_index)
  1028. try:
  1029. w_list.setitem(idx, w_any)
  1030. except IndexError:
  1031. raise OperationError(space.w_IndexError,
  1032. space.wrap("list index out of range"))
  1033. return space.w_None
  1034. def setitem__List_Slice_List(space, w_list, w_slice, w_other):
  1035. oldsize = w_list.length()
  1036. start, stop, step, slicelength = w_slice.indices4(space, oldsize)
  1037. w_list.setslice(start, step, slicelength, w_other)
  1038. def setitem__List_Slice_ANY(space, w_list, w_slice, w_iterable):
  1039. oldsize = w_list.length()
  1040. start, stop, step, slicelength = w_slice.indices4(space, oldsize)
  1041. sequence_w = space.listview(w_iterable)
  1042. w_other = W_ListObject(space, sequence_w)
  1043. w_list.setslice(start, step, slicelength, w_other)
  1044. app = gateway.applevel("""
  1045. def listrepr(currently_in_repr, l):
  1046. 'The app-level part of repr().'
  1047. list_id = id(l)
  1048. if list_id in currently_in_repr:
  1049. return '[...]'
  1050. currently_in_repr[list_id] = 1
  1051. try:
  1052. return "[" + ", ".join([repr(x) for x in l]) + ']'
  1053. finally:
  1054. try:
  1055. del currently_in_repr[list_id]
  1056. except:
  1057. pass
  1058. """, filename=__file__)
  1059. listrepr = app.interphook("listrepr")
  1060. def repr__List(space, w_list):
  1061. if w_list.length() == 0:
  1062. return space.wrap('[]')
  1063. ec = space.getexecutioncontext()
  1064. w_currently_in_repr = ec._py_repr
  1065. if w_currently_in_repr is None:
  1066. w_currently_in_repr = ec._py_repr = space.newdict()
  1067. return listrepr(space, w_currently_in_repr, w_list)
  1068. def list_insert__List_ANY_ANY(space, w_list, w_where, w_any):
  1069. where = space.int_w(w_where)
  1070. length = w_list.length()
  1071. index = get_positive_index(where, length)
  1072. w_list.insert(index, w_any)
  1073. return space.w_None
  1074. def get_positive_index(where, length):
  1075. if where < 0:
  1076. where += length
  1077. if where < 0:
  1078. where = 0
  1079. elif where > length:
  1080. where = length
  1081. assert where >= 0
  1082. return where
  1083. def list_append__List_ANY(space, w_list, w_any):
  1084. w_list.append(w_any)
  1085. return space.w_None
  1086. def list_extend__List_List(space, w_list, w_other):
  1087. w_list.extend(w_other)
  1088. return space.w_None
  1089. def list_extend__List_ANY(space, w_list, w_any):
  1090. w_other = W_ListObject(space, space.listview(w_any))
  1091. w_list.extend(w_other)
  1092. return space.w_None
  1093. # default of w_idx is space.w_None (see listtype.py)
  1094. def list_pop__List_ANY(space, w_list, w_idx):
  1095. length = w_list.length()
  1096. if length == 0:
  1097. raise OperationError(space.w_IndexError,
  1098. space.wrap("pop from empty list"))
  1099. # clearly differentiate between list.pop() and list.pop(index)
  1100. if space.is_w(w_idx, space.w_None):
  1101. return w_list.pop_end() # cannot raise because list is not empty
  1102. if space.isinstance_w(w_idx, space.w_float):
  1103. raise OperationError(space.w_TypeError,
  1104. space.wrap("integer argument expected, got float")
  1105. )
  1106. idx = space.int_w(space.int(w_idx))
  1107. if idx < 0:
  1108. idx += length
  1109. try:
  1110. return w_list.pop(idx)
  1111. except IndexError:
  1112. raise OperationError(space.w_IndexError,
  1113. space.wrap("pop index out of range"))
  1114. def list_remove__List_ANY(space, w_list, w_any):
  1115. # needs to be safe against eq_w() mutating the w_list behind our back
  1116. i = 0
  1117. while i < w_list.length():
  1118. if space.eq_w(w_list.getitem(i), w_any):
  1119. if i < w_list.length(): # if this is wrong the list was changed
  1120. w_list.pop(i)
  1121. return space.w_None
  1122. i += 1
  1123. raise OperationError(space.w_ValueError,
  1124. space.wrap("list.remove(x): x not in list"))
  1125. def list_index__List_ANY_ANY_ANY(space, w_list, w_any, w_start, w_stop):
  1126. # needs to be safe against eq_w() mutating the w_list behind our back
  1127. size = w_list.length()
  1128. i, stop = slicetype.unwrap_start_stop(
  1129. space, size, w_start, w_stop, True)
  1130. while i < stop and i < w_list.length():
  1131. if space.eq_w(w_list.getitem(i), w_any):
  1132. return space.wrap(i)
  1133. i += 1
  1134. raise OperationError(space.w_ValueError,
  1135. space.wrap("list.index(x): x not in list"))
  1136. def list_count__List_ANY(space, w_list, w_any):
  1137. # needs to be safe against eq_w() mutating the w_list behind our back
  1138. count = 0
  1139. i = 0
  1140. while i < w_list.length():
  1141. if space.eq_w(w_list.getitem(i), w_any):
  1142. count += 1
  1143. i += 1
  1144. return space.wrap(count)
  1145. def list_reverse__List(space, w_list):
  1146. w_list.reverse()
  1147. return space.w_None
  1148. # ____________________________________________________________
  1149. # Sorting
  1150. # Reverse a slice of a list in place, from lo up to (exclusive) hi.
  1151. # (used in sort)
  1152. TimSort = make_timsort_class()
  1153. IntBaseTimSort = make_timsort_class()
  1154. FloatBaseTimSort = make_timsort_class()
  1155. StringBaseTimSort = make_timsort_class()
  1156. class KeyContainer(baseobjspace.W_Root):
  1157. def __init__(self, w_key, w_item):
  1158. self.w_key = w_key
  1159. self.w_item = w_item
  1160. # NOTE: all the subclasses of TimSort should inherit from a common subclass,
  1161. # so make sure that only SimpleSort inherits directly from TimSort.
  1162. # This is necessary to hide the parent method TimSort.lt() from the
  1163. # annotator.
  1164. class SimpleSort(TimSort):
  1165. def lt(self, a, b):
  1166. space = self.space
  1167. return space.is_true(space.lt(a, b))
  1168. class IntSort(IntBaseTimSort):
  1169. def lt(self, a, b):
  1170. return a < b
  1171. class FloatSort(FloatBaseTimSort):
  1172. def lt(self, a, b):
  1173. return a < b
  1174. class StringSort(StringBaseTimSort):
  1175. def lt(self, a, b):
  1176. return a < b
  1177. class CustomCompareSort(SimpleSort):
  1178. def lt(self, a, b):
  1179. space = self.space
  1180. w_cmp = self.w_cmp
  1181. w_result = space.call_function(w_cmp, a, b)
  1182. try:
  1183. result = space.int_w(w_result)
  1184. except OperationError, e:
  1185. if e.match(space, space.w_TypeError):
  1186. raise OperationError(space.w_TypeError,
  1187. space.wrap("comparison function must return int"))
  1188. raise
  1189. return result < 0
  1190. class CustomKeySort(SimpleSort):
  1191. def lt(self, a, b):
  1192. assert isinstance(a, KeyContainer)
  1193. assert isinstance(b, KeyContainer)
  1194. space = self.space
  1195. return space.is_true(space.lt(a.w_key, b.w_key))
  1196. class CustomKeyCompareSort(CustomCompareSort):
  1197. def lt(self, a, b):
  1198. assert isinstance(a, KeyContainer)
  1199. assert isinstance(b, KeyContainer)
  1200. return CustomCompareSort.lt(self, a.w_key, b.w_key)
  1201. def list_sort__List_ANY_ANY_ANY(space, w_list, w_cmp, w_keyfunc, w_reverse):
  1202. has_cmp = not space.is_w(w_cmp, space.w_None)
  1203. has_key = not space.is_w(w_keyfunc, space.w_None)
  1204. has_reverse = space.is_true(w_reverse)
  1205. # create and setup a TimSort instance
  1206. if has_cmp:
  1207. if has_key:
  1208. sorterclass = CustomKeyCompareSort
  1209. else:
  1210. sorterclass = CustomCompareSort
  1211. else:
  1212. if has_key:
  1213. sorterclass = CustomKeySort
  1214. else:

Large files files are truncated, but you can click here to view the full file