PageRenderTime 58ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/objspace/std/listobject.py

https://bitbucket.org/pypy/pypy/
Python | 2182 lines | 2104 code | 53 blank | 25 comment | 42 complexity | dea1d5e21f252fdb2cef507b73756299 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0

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

  1. """The builtin list implementation
  2. Lists optimize their storage by holding certain primitive datatypes in
  3. unwrapped form. For more information:
  4. http://morepypy.blogspot.com/2011/10/more-compact-lists-with-list-strategies.html
  5. """
  6. import operator
  7. import sys
  8. from rpython.rlib import debug, jit, rerased
  9. from rpython.rlib.listsort import make_timsort_class
  10. from rpython.rlib.objectmodel import (
  11. import_from_mixin, instantiate, newlist_hint, resizelist_hint, specialize)
  12. from rpython.rlib import longlong2float
  13. from rpython.tool.sourcetools import func_with_new_name
  14. from pypy.interpreter.baseobjspace import W_Root
  15. from pypy.interpreter.error import OperationError, oefmt
  16. from pypy.interpreter.gateway import (
  17. WrappedDefault, applevel, interp2app, unwrap_spec)
  18. from pypy.interpreter.generator import GeneratorIterator
  19. from pypy.interpreter.signature import Signature
  20. from pypy.interpreter.typedef import TypeDef
  21. from pypy.objspace.std.bytesobject import W_BytesObject
  22. from pypy.objspace.std.floatobject import W_FloatObject
  23. from pypy.objspace.std.intobject import W_IntObject
  24. from pypy.objspace.std.iterobject import (
  25. W_FastListIterObject, W_ReverseSeqIterObject)
  26. from pypy.objspace.std.sliceobject import (
  27. W_SliceObject, normalize_simple_slice, unwrap_start_stop)
  28. from pypy.objspace.std.tupleobject import W_AbstractTupleObject
  29. from pypy.objspace.std.unicodeobject import W_UnicodeObject
  30. from pypy.objspace.std.util import get_positive_index, negate
  31. __all__ = ['W_ListObject', 'make_range_list', 'make_empty_list_with_size']
  32. UNROLL_CUTOFF = 5
  33. def make_range_list(space, start, step, length):
  34. if length <= 0:
  35. strategy = space.fromcache(EmptyListStrategy)
  36. storage = strategy.erase(None)
  37. elif start == 0 and step == 1:
  38. strategy = space.fromcache(SimpleRangeListStrategy)
  39. storage = strategy.erase((length,))
  40. else:
  41. strategy = space.fromcache(RangeListStrategy)
  42. storage = strategy.erase((start, step, length))
  43. return W_ListObject.from_storage_and_strategy(space, storage, strategy)
  44. def make_empty_list(space):
  45. strategy = space.fromcache(EmptyListStrategy)
  46. storage = strategy.erase(None)
  47. return W_ListObject.from_storage_and_strategy(space, storage, strategy)
  48. def make_empty_list_with_size(space, hint):
  49. strategy = SizeListStrategy(space, hint)
  50. storage = strategy.erase(None)
  51. return W_ListObject.from_storage_and_strategy(space, storage, strategy)
  52. @jit.look_inside_iff(lambda space, list_w, sizehint:
  53. jit.loop_unrolling_heuristic(list_w, len(list_w), UNROLL_CUTOFF))
  54. def get_strategy_from_list_objects(space, list_w, sizehint):
  55. if not list_w:
  56. if sizehint != -1:
  57. return SizeListStrategy(space, sizehint)
  58. return space.fromcache(EmptyListStrategy)
  59. w_firstobj = list_w[0]
  60. check_int_or_float = False
  61. if type(w_firstobj) is W_IntObject:
  62. # check for all-ints
  63. for i in range(1, len(list_w)):
  64. w_obj = list_w[i]
  65. if type(w_obj) is not W_IntObject:
  66. check_int_or_float = (type(w_obj) is W_FloatObject)
  67. break
  68. else:
  69. return space.fromcache(IntegerListStrategy)
  70. elif type(w_firstobj) is W_BytesObject:
  71. # check for all-strings
  72. for i in range(1, len(list_w)):
  73. if type(list_w[i]) is not W_BytesObject:
  74. break
  75. else:
  76. return space.fromcache(BytesListStrategy)
  77. elif type(w_firstobj) is W_UnicodeObject:
  78. # check for all-unicodes
  79. for i in range(1, len(list_w)):
  80. if type(list_w[i]) is not W_UnicodeObject:
  81. break
  82. else:
  83. return space.fromcache(UnicodeListStrategy)
  84. elif type(w_firstobj) is W_FloatObject:
  85. # check for all-floats
  86. for i in range(1, len(list_w)):
  87. w_obj = list_w[i]
  88. if type(w_obj) is not W_FloatObject:
  89. check_int_or_float = (type(w_obj) is W_IntObject)
  90. break
  91. else:
  92. return space.fromcache(FloatListStrategy)
  93. if check_int_or_float:
  94. for w_obj in list_w:
  95. if type(w_obj) is W_IntObject:
  96. if longlong2float.can_encode_int32(space.int_w(w_obj)):
  97. continue # ok
  98. elif type(w_obj) is W_FloatObject:
  99. if longlong2float.can_encode_float(space.float_w(w_obj)):
  100. continue # ok
  101. break
  102. else:
  103. return space.fromcache(IntOrFloatListStrategy)
  104. return space.fromcache(ObjectListStrategy)
  105. def _get_printable_location(w_type):
  106. return ('list__do_extend_from_iterable [w_type=%s]' %
  107. w_type.getname(w_type.space))
  108. _do_extend_jitdriver = jit.JitDriver(
  109. name='list__do_extend_from_iterable',
  110. greens=['w_type'],
  111. reds=['i', 'w_iterator', 'w_list'],
  112. get_printable_location=_get_printable_location)
  113. def _do_extend_from_iterable(space, w_list, w_iterable):
  114. w_iterator = space.iter(w_iterable)
  115. w_type = space.type(w_iterator)
  116. i = 0
  117. while True:
  118. _do_extend_jitdriver.jit_merge_point(w_type=w_type,
  119. i=i,
  120. w_iterator=w_iterator,
  121. w_list=w_list)
  122. try:
  123. w_list.append(space.next(w_iterator))
  124. except OperationError as e:
  125. if not e.match(space, space.w_StopIteration):
  126. raise
  127. break
  128. i += 1
  129. return i
  130. def list_unroll_condition(w_list1, space, w_list2):
  131. return (jit.loop_unrolling_heuristic(w_list1, w_list1.length(),
  132. UNROLL_CUTOFF) or
  133. jit.loop_unrolling_heuristic(w_list2, w_list2.length(),
  134. UNROLL_CUTOFF))
  135. class W_ListObject(W_Root):
  136. strategy = None
  137. def __init__(self, space, wrappeditems, sizehint=-1):
  138. assert isinstance(wrappeditems, list)
  139. self.space = space
  140. if space.config.objspace.std.withliststrategies:
  141. self.strategy = get_strategy_from_list_objects(space, wrappeditems,
  142. sizehint)
  143. else:
  144. self.strategy = space.fromcache(ObjectListStrategy)
  145. self.init_from_list_w(wrappeditems)
  146. @staticmethod
  147. def from_storage_and_strategy(space, storage, strategy):
  148. self = instantiate(W_ListObject)
  149. self.space = space
  150. self.strategy = strategy
  151. self.lstorage = storage
  152. if not space.config.objspace.std.withliststrategies:
  153. self.switch_to_object_strategy()
  154. return self
  155. @staticmethod
  156. def newlist_bytes(space, list_b):
  157. strategy = space.fromcache(BytesListStrategy)
  158. storage = strategy.erase(list_b)
  159. return W_ListObject.from_storage_and_strategy(space, storage, strategy)
  160. @staticmethod
  161. def newlist_unicode(space, list_u):
  162. strategy = space.fromcache(UnicodeListStrategy)
  163. storage = strategy.erase(list_u)
  164. return W_ListObject.from_storage_and_strategy(space, storage, strategy)
  165. @staticmethod
  166. def newlist_int(space, list_i):
  167. strategy = space.fromcache(IntegerListStrategy)
  168. storage = strategy.erase(list_i)
  169. return W_ListObject.from_storage_and_strategy(space, storage, strategy)
  170. @staticmethod
  171. def newlist_float(space, list_f):
  172. strategy = space.fromcache(FloatListStrategy)
  173. storage = strategy.erase(list_f)
  174. return W_ListObject.from_storage_and_strategy(space, storage, strategy)
  175. @staticmethod
  176. def newlist_cpyext(space, list):
  177. from pypy.module.cpyext.sequence import CPyListStrategy, CPyListStorage
  178. strategy = space.fromcache(CPyListStrategy)
  179. storage = strategy.erase(CPyListStorage(space, list))
  180. return W_ListObject.from_storage_and_strategy(space, storage, strategy)
  181. def __repr__(self):
  182. """ representation for debugging purposes """
  183. return "%s(%s, %s)" % (self.__class__.__name__, self.strategy,
  184. self.lstorage._x)
  185. def unwrap(w_list, space):
  186. # for tests only!
  187. items = [space.unwrap(w_item) for w_item in w_list.getitems()]
  188. return list(items)
  189. def switch_to_object_strategy(self):
  190. list_w = self.getitems()
  191. object_strategy = self.space.fromcache(ObjectListStrategy)
  192. self.strategy = object_strategy
  193. object_strategy.init_from_list_w(self, list_w)
  194. def ensure_object_strategy(self): # for cpyext
  195. if self.strategy is not self.space.fromcache(ObjectListStrategy):
  196. self.switch_to_object_strategy()
  197. def _temporarily_as_objects(self):
  198. if self.strategy is self.space.fromcache(ObjectListStrategy):
  199. return self
  200. list_w = self.getitems()
  201. strategy = self.space.fromcache(ObjectListStrategy)
  202. storage = strategy.erase(list_w)
  203. w_objectlist = W_ListObject.from_storage_and_strategy(
  204. self.space, storage, strategy)
  205. return w_objectlist
  206. def convert_to_cpy_strategy(self, space):
  207. from pypy.module.cpyext.sequence import CPyListStorage, CPyListStrategy
  208. cpy_strategy = self.space.fromcache(CPyListStrategy)
  209. if self.strategy is cpy_strategy:
  210. return
  211. lst = self.getitems()
  212. self.strategy = cpy_strategy
  213. self.lstorage = cpy_strategy.erase(CPyListStorage(space, lst))
  214. def get_raw_items(self):
  215. from pypy.module.cpyext.sequence import CPyListStrategy
  216. cpy_strategy = self.space.fromcache(CPyListStrategy)
  217. assert self.strategy is cpy_strategy # should we return an error?
  218. return cpy_strategy.get_raw_items(self)
  219. # ___________________________________________________
  220. def init_from_list_w(self, list_w):
  221. """Initializes listobject by iterating through the given list of
  222. wrapped items, unwrapping them if neccessary and creating a
  223. new erased object as storage"""
  224. self.strategy.init_from_list_w(self, list_w)
  225. def clear(self, space):
  226. """Initializes (or overrides) the listobject as empty."""
  227. self.space = space
  228. if space.config.objspace.std.withliststrategies:
  229. strategy = space.fromcache(EmptyListStrategy)
  230. else:
  231. strategy = space.fromcache(ObjectListStrategy)
  232. self.strategy = strategy
  233. strategy.clear(self)
  234. def clone(self):
  235. """Returns a clone by creating a new listobject
  236. with the same strategy and a copy of the storage"""
  237. return self.strategy.clone(self)
  238. def _resize_hint(self, hint):
  239. """Ensure the underlying list has room for at least hint
  240. elements without changing the len() of the list"""
  241. return self.strategy._resize_hint(self, hint)
  242. def copy_into(self, other):
  243. """Used only when extending an EmptyList. Sets the EmptyLists
  244. strategy and storage according to the other W_List"""
  245. self.strategy.copy_into(self, other)
  246. def find(self, w_item, start=0, end=sys.maxint):
  247. """Find w_item in list[start:end]. If not found, raise ValueError"""
  248. return self.strategy.find(self, w_item, start, end)
  249. def append(self, w_item):
  250. """L.append(object) -- append object to end"""
  251. self.strategy.append(self, w_item)
  252. def length(self):
  253. return self.strategy.length(self)
  254. def getitem(self, index):
  255. """Returns the wrapped object that is found in the
  256. list at the given index. The index must be unwrapped.
  257. May raise IndexError."""
  258. return self.strategy.getitem(self, index)
  259. def getslice(self, start, stop, step, length):
  260. """Returns a slice of the list defined by the arguments. Arguments must
  261. be normalized (i.e. using normalize_simple_slice or W_Slice.indices4).
  262. May raise IndexError."""
  263. return self.strategy.getslice(self, start, stop, step, length)
  264. def getitems(self):
  265. """Returns a list of all items after wrapping them. The result can
  266. share with the storage, if possible."""
  267. return self.strategy.getitems(self)
  268. def getitems_fixedsize(self):
  269. """Returns a fixed-size list of all items after wrapping them."""
  270. l = self.strategy.getitems_fixedsize(self)
  271. debug.make_sure_not_resized(l)
  272. return l
  273. def getitems_unroll(self):
  274. """Returns a fixed-size list of all items after wrapping them. The JIT
  275. will fully unroll this function."""
  276. l = self.strategy.getitems_unroll(self)
  277. debug.make_sure_not_resized(l)
  278. return l
  279. def getitems_copy(self):
  280. """Returns a copy of all items in the list. Same as getitems except for
  281. ObjectListStrategy."""
  282. return self.strategy.getitems_copy(self)
  283. def getitems_bytes(self):
  284. """Return the items in the list as unwrapped strings. If the list does
  285. not use the list strategy, return None."""
  286. return self.strategy.getitems_bytes(self)
  287. def getitems_unicode(self):
  288. """Return the items in the list as unwrapped unicodes. If the list does
  289. not use the list strategy, return None."""
  290. return self.strategy.getitems_unicode(self)
  291. def getitems_int(self):
  292. """Return the items in the list as unwrapped ints. If the list does not
  293. use the list strategy, return None."""
  294. return self.strategy.getitems_int(self)
  295. def getitems_float(self):
  296. """Return the items in the list as unwrapped floats. If the list does not
  297. use the list strategy, return None."""
  298. return self.strategy.getitems_float(self)
  299. # ___________________________________________________
  300. def mul(self, times):
  301. """Returns a copy of the list, multiplied by times.
  302. Argument must be unwrapped."""
  303. return self.strategy.mul(self, times)
  304. def inplace_mul(self, times):
  305. """Alters the list by multiplying its content by times."""
  306. self.strategy.inplace_mul(self, times)
  307. def deleteslice(self, start, step, length):
  308. """Deletes a slice from the list. Used in delitem and delslice.
  309. Arguments must be normalized (see getslice)."""
  310. self.strategy.deleteslice(self, start, step, length)
  311. def pop(self, index):
  312. """Pops an item from the list. Index must be normalized.
  313. May raise IndexError."""
  314. return self.strategy.pop(self, index)
  315. def pop_end(self):
  316. """ Pop the last element from the list."""
  317. return self.strategy.pop_end(self)
  318. def setitem(self, index, w_item):
  319. """Inserts a wrapped item at the given (unwrapped) index.
  320. May raise IndexError."""
  321. self.strategy.setitem(self, index, w_item)
  322. def setslice(self, start, step, slicelength, sequence_w):
  323. """Sets the slice of the list from start to start+step*slicelength to
  324. the sequence sequence_w.
  325. Used by setslice and setitem."""
  326. self.strategy.setslice(self, start, step, slicelength, sequence_w)
  327. def insert(self, index, w_item):
  328. """Inserts an item at the given position. Item must be wrapped,
  329. index not."""
  330. self.strategy.insert(self, index, w_item)
  331. def extend(self, w_iterable):
  332. '''L.extend(iterable) -- extend list by appending
  333. elements from the iterable'''
  334. self.strategy.extend(self, w_iterable)
  335. def reverse(self):
  336. """Reverses the list."""
  337. self.strategy.reverse(self)
  338. def sort(self, reverse):
  339. """Sorts the list ascending or descending depending on
  340. argument reverse. Argument must be unwrapped."""
  341. self.strategy.sort(self, reverse)
  342. # exposed to app-level
  343. @staticmethod
  344. def descr_new(space, w_listtype, __args__):
  345. """T.__new__(S, ...) -> a new object with type S, a subtype of T"""
  346. w_obj = space.allocate_instance(W_ListObject, w_listtype)
  347. w_obj.clear(space)
  348. return w_obj
  349. def descr_init(self, space, __args__):
  350. """x.__init__(...) initializes x; see help(type(x)) for signature"""
  351. # this is on the silly side
  352. w_iterable, = __args__.parse_obj(
  353. None, 'list', init_signature, init_defaults)
  354. self.clear(space)
  355. if w_iterable is not None:
  356. self.extend(w_iterable)
  357. def descr_repr(self, space):
  358. if self.length() == 0:
  359. return space.wrap('[]')
  360. ec = space.getexecutioncontext()
  361. w_currently_in_repr = ec._py_repr
  362. if w_currently_in_repr is None:
  363. w_currently_in_repr = ec._py_repr = space.newdict()
  364. return listrepr(space, w_currently_in_repr, self)
  365. def descr_eq(self, space, w_other):
  366. if not isinstance(w_other, W_ListObject):
  367. return space.w_NotImplemented
  368. return self._descr_eq(space, w_other)
  369. @jit.look_inside_iff(list_unroll_condition)
  370. def _descr_eq(self, space, w_other):
  371. # needs to be safe against eq_w() mutating the w_lists behind our back
  372. if self.length() != w_other.length():
  373. return space.w_False
  374. # XXX in theory, this can be implemented more efficiently as well.
  375. # let's not care for now
  376. i = 0
  377. while i < self.length() and i < w_other.length():
  378. if not space.eq_w(self.getitem(i), w_other.getitem(i)):
  379. return space.w_False
  380. i += 1
  381. return space.w_True
  382. descr_ne = negate(descr_eq)
  383. def _make_list_comparison(name):
  384. op = getattr(operator, name)
  385. def compare_unwrappeditems(self, space, w_list2):
  386. if not isinstance(w_list2, W_ListObject):
  387. return space.w_NotImplemented
  388. return _compare_unwrappeditems(self, space, w_list2)
  389. @jit.look_inside_iff(list_unroll_condition)
  390. def _compare_unwrappeditems(self, space, w_list2):
  391. # needs to be safe against eq_w() mutating the w_lists behind our
  392. # back
  393. # Search for the first index where items are different
  394. i = 0
  395. # XXX in theory, this can be implemented more efficiently as well.
  396. # let's not care for now
  397. while i < self.length() and i < w_list2.length():
  398. w_item1 = self.getitem(i)
  399. w_item2 = w_list2.getitem(i)
  400. if not space.eq_w(w_item1, w_item2):
  401. return getattr(space, name)(w_item1, w_item2)
  402. i += 1
  403. # No more items to compare -- compare sizes
  404. return space.newbool(op(self.length(), w_list2.length()))
  405. return func_with_new_name(compare_unwrappeditems, 'descr_' + name)
  406. descr_lt = _make_list_comparison('lt')
  407. descr_le = _make_list_comparison('le')
  408. descr_gt = _make_list_comparison('gt')
  409. descr_ge = _make_list_comparison('ge')
  410. def descr_len(self, space):
  411. result = self.length()
  412. return space.newint(result)
  413. def descr_iter(self, space):
  414. return W_FastListIterObject(self)
  415. def descr_contains(self, space, w_obj):
  416. try:
  417. self.find(w_obj)
  418. return space.w_True
  419. except ValueError:
  420. return space.w_False
  421. def descr_add(self, space, w_list2):
  422. if not isinstance(w_list2, W_ListObject):
  423. return space.w_NotImplemented
  424. w_clone = self.clone()
  425. w_clone.extend(w_list2)
  426. return w_clone
  427. def descr_inplace_add(self, space, w_iterable):
  428. if isinstance(w_iterable, W_ListObject):
  429. self.extend(w_iterable)
  430. return self
  431. try:
  432. self.extend(w_iterable)
  433. except OperationError as e:
  434. if e.match(space, space.w_TypeError):
  435. return space.w_NotImplemented
  436. raise
  437. return self
  438. def descr_mul(self, space, w_times):
  439. try:
  440. times = space.getindex_w(w_times, space.w_OverflowError)
  441. except OperationError as e:
  442. if e.match(space, space.w_TypeError):
  443. return space.w_NotImplemented
  444. raise
  445. return self.mul(times)
  446. def descr_inplace_mul(self, space, w_times):
  447. try:
  448. times = space.getindex_w(w_times, space.w_OverflowError)
  449. except OperationError as e:
  450. if e.match(space, space.w_TypeError):
  451. return space.w_NotImplemented
  452. raise
  453. self.inplace_mul(times)
  454. return self
  455. def descr_getitem(self, space, w_index):
  456. if isinstance(w_index, W_SliceObject):
  457. length = self.length()
  458. start, stop, step, slicelength = w_index.indices4(space, length)
  459. assert slicelength >= 0
  460. if slicelength == 0:
  461. return make_empty_list(space)
  462. return self.getslice(start, stop, step, slicelength)
  463. try:
  464. index = space.getindex_w(w_index, space.w_IndexError, "list index")
  465. return self.getitem(index)
  466. except IndexError:
  467. raise oefmt(space.w_IndexError, "list index out of range")
  468. def descr_getslice(self, space, w_start, w_stop):
  469. length = self.length()
  470. start, stop = normalize_simple_slice(space, length, w_start, w_stop)
  471. slicelength = stop - start
  472. if slicelength == 0:
  473. return make_empty_list(space)
  474. return self.getslice(start, stop, 1, stop - start)
  475. def descr_setitem(self, space, w_index, w_any):
  476. if isinstance(w_index, W_SliceObject):
  477. oldsize = self.length()
  478. start, stop, step, slicelength = w_index.indices4(space, oldsize)
  479. if isinstance(w_any, W_ListObject):
  480. self.setslice(start, step, slicelength, w_any)
  481. else:
  482. sequence_w = space.listview(w_any)
  483. w_other = W_ListObject(space, sequence_w)
  484. self.setslice(start, step, slicelength, w_other)
  485. return
  486. idx = space.getindex_w(w_index, space.w_IndexError, "list index")
  487. try:
  488. self.setitem(idx, w_any)
  489. except IndexError:
  490. raise oefmt(space.w_IndexError, "list index out of range")
  491. def descr_setslice(self, space, w_start, w_stop, w_iterable):
  492. length = self.length()
  493. start, stop = normalize_simple_slice(space, length, w_start, w_stop)
  494. if isinstance(w_iterable, W_ListObject):
  495. self.setslice(start, 1, stop - start, w_iterable)
  496. else:
  497. sequence_w = space.listview(w_iterable)
  498. w_other = W_ListObject(space, sequence_w)
  499. self.setslice(start, 1, stop - start, w_other)
  500. def descr_delitem(self, space, w_idx):
  501. if isinstance(w_idx, W_SliceObject):
  502. start, stop, step, slicelength = w_idx.indices4(
  503. space, self.length())
  504. self.deleteslice(start, step, slicelength)
  505. return
  506. idx = space.getindex_w(w_idx, space.w_IndexError, "list index")
  507. if idx < 0:
  508. idx += self.length()
  509. try:
  510. self.pop(idx)
  511. except IndexError:
  512. raise oefmt(space.w_IndexError, "list index out of range")
  513. def descr_delslice(self, space, w_start, w_stop):
  514. length = self.length()
  515. start, stop = normalize_simple_slice(space, length, w_start, w_stop)
  516. self.deleteslice(start, 1, stop - start)
  517. def descr_reversed(self, space):
  518. 'L.__reversed__() -- return a reverse iterator over the list'
  519. return W_ReverseSeqIterObject(space, self, -1)
  520. def descr_reverse(self, space):
  521. 'L.reverse() -- reverse *IN PLACE*'
  522. self.reverse()
  523. def descr_count(self, space, w_value):
  524. '''L.count(value) -> integer -- return number of
  525. occurrences of value'''
  526. # needs to be safe against eq_w() mutating the w_list behind our back
  527. count = 0
  528. i = 0
  529. while i < self.length():
  530. if space.eq_w(self.getitem(i), w_value):
  531. count += 1
  532. i += 1
  533. return space.wrap(count)
  534. @unwrap_spec(index=int)
  535. def descr_insert(self, space, index, w_value):
  536. 'L.insert(index, object) -- insert object before index'
  537. length = self.length()
  538. index = get_positive_index(index, length)
  539. self.insert(index, w_value)
  540. @unwrap_spec(index=int)
  541. def descr_pop(self, space, index=-1):
  542. '''L.pop([index]) -> item -- remove and return item at
  543. index (default last)'''
  544. length = self.length()
  545. if length == 0:
  546. raise oefmt(space.w_IndexError, "pop from empty list")
  547. # clearly differentiate between list.pop() and list.pop(index)
  548. if index == -1:
  549. return self.pop_end() # cannot raise because list is not empty
  550. if index < 0:
  551. index += length
  552. try:
  553. return self.pop(index)
  554. except IndexError:
  555. raise oefmt(space.w_IndexError, "pop index out of range")
  556. def descr_remove(self, space, w_value):
  557. 'L.remove(value) -- remove first occurrence of value'
  558. # needs to be safe against eq_w() mutating the w_list behind our back
  559. try:
  560. i = self.find(w_value, 0, sys.maxint)
  561. except ValueError:
  562. raise oefmt(space.w_ValueError,
  563. "list.remove(): %R is not in list", w_value)
  564. if i < self.length(): # otherwise list was mutated
  565. self.pop(i)
  566. @unwrap_spec(w_start=WrappedDefault(0), w_stop=WrappedDefault(sys.maxint))
  567. def descr_index(self, space, w_value, w_start, w_stop):
  568. '''L.index(value, [start, [stop]]) -> integer -- return
  569. first index of value'''
  570. # needs to be safe against eq_w() mutating the w_list behind our back
  571. size = self.length()
  572. i, stop = unwrap_start_stop(space, size, w_start, w_stop)
  573. # note that 'i' and 'stop' can be bigger than the length of the list
  574. try:
  575. i = self.find(w_value, i, stop)
  576. except ValueError:
  577. raise oefmt(space.w_ValueError, "%R is not in list", w_value)
  578. return space.wrap(i)
  579. @unwrap_spec(reverse=bool)
  580. def descr_sort(self, space, w_cmp=None, w_key=None, reverse=False):
  581. """ L.sort(cmp=None, key=None, reverse=False) -- stable
  582. sort *IN PLACE*;
  583. cmp(x, y) -> -1, 0, 1"""
  584. has_cmp = not space.is_none(w_cmp)
  585. has_key = not space.is_none(w_key)
  586. # create and setup a TimSort instance
  587. if has_cmp:
  588. if has_key:
  589. sorterclass = CustomKeyCompareSort
  590. else:
  591. sorterclass = CustomCompareSort
  592. else:
  593. if has_key:
  594. sorterclass = CustomKeySort
  595. else:
  596. if self.strategy is space.fromcache(ObjectListStrategy):
  597. sorterclass = SimpleSort
  598. else:
  599. self.sort(reverse)
  600. return
  601. sorter = sorterclass(self.getitems(), self.length())
  602. sorter.space = space
  603. sorter.w_cmp = w_cmp
  604. try:
  605. # The list is temporarily made empty, so that mutations performed
  606. # by comparison functions can't affect the slice of memory we're
  607. # sorting (allowing mutations during sorting is an IndexError or
  608. # core-dump factory, since the storage may change).
  609. self.__init__(space, [])
  610. # wrap each item in a KeyContainer if needed
  611. if has_key:
  612. for i in range(sorter.listlength):
  613. w_item = sorter.list[i]
  614. w_keyitem = space.call_function(w_key, w_item)
  615. sorter.list[i] = KeyContainer(w_keyitem, w_item)
  616. # Reverse sort stability achieved by initially reversing the list,
  617. # applying a stable forward sort, then reversing the final result.
  618. if reverse:
  619. sorter.list.reverse()
  620. # perform the sort
  621. sorter.sort()
  622. # reverse again
  623. if reverse:
  624. sorter.list.reverse()
  625. finally:
  626. # unwrap each item if needed
  627. if has_key:
  628. for i in range(sorter.listlength):
  629. w_obj = sorter.list[i]
  630. if isinstance(w_obj, KeyContainer):
  631. sorter.list[i] = w_obj.w_item
  632. # check if the user mucked with the list during the sort
  633. mucked = self.length() > 0
  634. # put the items back into the list
  635. self.__init__(space, sorter.list)
  636. if mucked:
  637. raise oefmt(space.w_ValueError, "list modified during sort")
  638. find_jmp = jit.JitDriver(greens = ['tp'], reds = 'auto', name = 'list.find')
  639. class ListStrategy(object):
  640. def __init__(self, space):
  641. self.space = space
  642. def get_sizehint(self):
  643. return -1
  644. def init_from_list_w(self, w_list, list_w):
  645. raise NotImplementedError
  646. def clone(self, w_list):
  647. raise NotImplementedError
  648. def copy_into(self, w_list, w_other):
  649. raise NotImplementedError
  650. def _resize_hint(self, w_list, hint):
  651. raise NotImplementedError
  652. def find(self, w_list, w_item, start, stop):
  653. space = self.space
  654. i = start
  655. # needs to be safe against eq_w mutating stuff
  656. tp = space.type(w_item)
  657. while i < stop and i < w_list.length():
  658. find_jmp.jit_merge_point(tp=tp)
  659. if space.eq_w(w_item, w_list.getitem(i)):
  660. return i
  661. i += 1
  662. raise ValueError
  663. def length(self, w_list):
  664. raise NotImplementedError
  665. def getitem(self, w_list, index):
  666. raise NotImplementedError
  667. def getslice(self, w_list, start, stop, step, length):
  668. raise NotImplementedError
  669. def getitems(self, w_list):
  670. return self.getitems_copy(w_list)
  671. def getitems_copy(self, w_list):
  672. raise NotImplementedError
  673. def getitems_bytes(self, w_list):
  674. return None
  675. def getitems_unicode(self, w_list):
  676. return None
  677. def getitems_int(self, w_list):
  678. return None
  679. def getitems_float(self, w_list):
  680. return None
  681. def getstorage_copy(self, w_list):
  682. raise NotImplementedError
  683. def append(self, w_list, w_item):
  684. raise NotImplementedError
  685. def mul(self, w_list, times):
  686. w_newlist = w_list.clone()
  687. w_newlist.inplace_mul(times)
  688. return w_newlist
  689. def inplace_mul(self, w_list, times):
  690. raise NotImplementedError
  691. def deleteslice(self, w_list, start, step, slicelength):
  692. raise NotImplementedError
  693. def pop(self, w_list, index):
  694. raise NotImplementedError
  695. def pop_end(self, w_list):
  696. return self.pop(w_list, self.length(w_list) - 1)
  697. def setitem(self, w_list, index, w_item):
  698. raise NotImplementedError
  699. def setslice(self, w_list, start, step, slicelength, sequence_w):
  700. raise NotImplementedError
  701. def insert(self, w_list, index, w_item):
  702. raise NotImplementedError
  703. def extend(self, w_list, w_any):
  704. if type(w_any) is W_ListObject or (isinstance(w_any, W_ListObject) and
  705. self.space._uses_list_iter(w_any)):
  706. self._extend_from_list(w_list, w_any)
  707. elif isinstance(w_any, GeneratorIterator):
  708. w_any.unpack_into_w(w_list)
  709. else:
  710. self._extend_from_iterable(w_list, w_any)
  711. def _extend_from_list(self, w_list, w_other):
  712. raise NotImplementedError
  713. def _extend_from_iterable(self, w_list, w_iterable):
  714. """Extend w_list from a generic iterable"""
  715. length_hint = self.space.length_hint(w_iterable, 0)
  716. if length_hint:
  717. w_list._resize_hint(w_list.length() + length_hint)
  718. extended = _do_extend_from_iterable(self.space, w_list, w_iterable)
  719. # cut back if the length hint was too large
  720. if extended < length_hint:
  721. w_list._resize_hint(w_list.length())
  722. def reverse(self, w_list):
  723. raise NotImplementedError
  724. def sort(self, w_list, reverse):
  725. raise NotImplementedError
  726. def is_empty_strategy(self):
  727. return False
  728. class EmptyListStrategy(ListStrategy):
  729. """EmptyListStrategy is used when a W_List withouth elements is created.
  730. The storage is None. When items are added to the W_List a new RPython list
  731. is created and the strategy and storage of the W_List are changed depending
  732. to the added item.
  733. W_Lists do not switch back to EmptyListStrategy when becoming empty again.
  734. """
  735. def __init__(self, space):
  736. ListStrategy.__init__(self, space)
  737. def init_from_list_w(self, w_list, list_w):
  738. assert len(list_w) == 0
  739. w_list.lstorage = self.erase(None)
  740. def clear(self, w_list):
  741. w_list.lstorage = self.erase(None)
  742. erase, unerase = rerased.new_erasing_pair("empty")
  743. erase = staticmethod(erase)
  744. unerase = staticmethod(unerase)
  745. def clone(self, w_list):
  746. return W_ListObject.from_storage_and_strategy(
  747. self.space, w_list.lstorage, self)
  748. def copy_into(self, w_list, w_other):
  749. pass
  750. def _resize_hint(self, w_list, hint):
  751. assert hint >= 0
  752. if hint:
  753. w_list.strategy = SizeListStrategy(self.space, hint)
  754. def find(self, w_list, w_item, start, stop):
  755. raise ValueError
  756. def length(self, w_list):
  757. return 0
  758. def getitem(self, w_list, index):
  759. raise IndexError
  760. def getslice(self, w_list, start, stop, step, length):
  761. # will never be called because the empty list case is already caught in
  762. # getslice__List_ANY_ANY and getitem__List_Slice
  763. return W_ListObject(self.space, [])
  764. def getitems(self, w_list):
  765. return []
  766. def getitems_copy(self, w_list):
  767. return []
  768. getitems_fixedsize = func_with_new_name(getitems_copy,
  769. "getitems_fixedsize")
  770. getitems_unroll = getitems_fixedsize
  771. def getstorage_copy(self, w_list):
  772. return self.erase(None)
  773. def switch_to_correct_strategy(self, w_list, w_item):
  774. if type(w_item) is W_IntObject:
  775. strategy = self.space.fromcache(IntegerListStrategy)
  776. elif type(w_item) is W_BytesObject:
  777. strategy = self.space.fromcache(BytesListStrategy)
  778. elif type(w_item) is W_UnicodeObject:
  779. strategy = self.space.fromcache(UnicodeListStrategy)
  780. elif type(w_item) is W_FloatObject:
  781. strategy = self.space.fromcache(FloatListStrategy)
  782. else:
  783. strategy = self.space.fromcache(ObjectListStrategy)
  784. storage = strategy.get_empty_storage(self.get_sizehint())
  785. w_list.strategy = strategy
  786. w_list.lstorage = storage
  787. def append(self, w_list, w_item):
  788. self.switch_to_correct_strategy(w_list, w_item)
  789. w_list.append(w_item)
  790. def inplace_mul(self, w_list, times):
  791. return
  792. def deleteslice(self, w_list, start, step, slicelength):
  793. pass
  794. def pop(self, w_list, index):
  795. # will not be called because IndexError was already raised in
  796. # list_pop__List_ANY
  797. raise IndexError
  798. def setitem(self, w_list, index, w_item):
  799. raise IndexError
  800. def setslice(self, w_list, start, step, slicelength, w_other):
  801. strategy = w_other.strategy
  802. storage = strategy.getstorage_copy(w_other)
  803. w_list.strategy = strategy
  804. w_list.lstorage = storage
  805. def sort(self, w_list, reverse):
  806. return
  807. def insert(self, w_list, index, w_item):
  808. assert index == 0
  809. self.append(w_list, w_item)
  810. def _extend_from_list(self, w_list, w_other):
  811. w_other.copy_into(w_list)
  812. def _extend_from_iterable(self, w_list, w_iterable):
  813. space = self.space
  814. if (isinstance(w_iterable, W_AbstractTupleObject)
  815. and space._uses_tuple_iter(w_iterable)):
  816. w_list.__init__(space, w_iterable.getitems_copy())
  817. return
  818. intlist = space.unpackiterable_int(w_iterable)
  819. if intlist is not None:
  820. w_list.strategy = strategy = space.fromcache(IntegerListStrategy)
  821. w_list.lstorage = strategy.erase(intlist)
  822. return
  823. floatlist = space.unpackiterable_float(w_iterable)
  824. if floatlist is not None:
  825. w_list.strategy = strategy = space.fromcache(FloatListStrategy)
  826. w_list.lstorage = strategy.erase(floatlist)
  827. return
  828. byteslist = space.listview_bytes(w_iterable)
  829. if byteslist is not None:
  830. w_list.strategy = strategy = space.fromcache(BytesListStrategy)
  831. # need to copy because intlist can share with w_iterable
  832. w_list.lstorage = strategy.erase(byteslist[:])
  833. return
  834. unilist = space.listview_unicode(w_iterable)
  835. if unilist is not None:
  836. w_list.strategy = strategy = space.fromcache(UnicodeListStrategy)
  837. # need to copy because intlist can share with w_iterable
  838. w_list.lstorage = strategy.erase(unilist[:])
  839. return
  840. ListStrategy._extend_from_iterable(self, w_list, w_iterable)
  841. def reverse(self, w_list):
  842. pass
  843. def is_empty_strategy(self):
  844. return True
  845. class SizeListStrategy(EmptyListStrategy):
  846. """Like empty, but when modified it'll preallocate the size to sizehint."""
  847. def __init__(self, space, sizehint):
  848. self.sizehint = sizehint
  849. ListStrategy.__init__(self, space)
  850. def get_sizehint(self):
  851. return self.sizehint
  852. def _resize_hint(self, w_list, hint):
  853. assert hint >= 0
  854. self.sizehint = hint
  855. class BaseRangeListStrategy(ListStrategy):
  856. def switch_to_integer_strategy(self, w_list):
  857. items = self._getitems_range(w_list, False)
  858. strategy = w_list.strategy = self.space.fromcache(IntegerListStrategy)
  859. w_list.lstorage = strategy.erase(items)
  860. def wrap(self, intval):
  861. return self.space.wrap(intval)
  862. def unwrap(self, w_int):
  863. return self.space.int_w(w_int)
  864. def init_from_list_w(self, w_list, list_w):
  865. raise NotImplementedError
  866. def clone(self, w_list):
  867. storage = w_list.lstorage # lstorage is tuple, no need to clone
  868. w_clone = W_ListObject.from_storage_and_strategy(self.space, storage,
  869. self)
  870. return w_clone
  871. def _resize_hint(self, w_list, hint):
  872. # XXX: this could be supported
  873. assert hint >= 0
  874. def copy_into(self, w_list, w_other):
  875. w_other.strategy = self
  876. w_other.lstorage = w_list.lstorage
  877. def getitem(self, w_list, i):
  878. return self.wrap(self._getitem_unwrapped(w_list, i))
  879. def getitems_int(self, w_list):
  880. return self._getitems_range(w_list, False)
  881. def getitems_copy(self, w_list):
  882. return self._getitems_range(w_list, True)
  883. def getstorage_copy(self, w_list):
  884. # tuple is immutable
  885. return w_list.lstorage
  886. @jit.dont_look_inside
  887. def getitems_fixedsize(self, w_list):
  888. return self._getitems_range_unroll(w_list, True)
  889. def getitems_unroll(self, w_list):
  890. return self._getitems_range_unroll(w_list, True)
  891. def getslice(self, w_list, start, stop, step, length):
  892. self.switch_to_integer_strategy(w_list)
  893. return w_list.getslice(start, stop, step, length)
  894. def append(self, w_list, w_item):
  895. if type(w_item) is W_IntObject:
  896. self.switch_to_integer_strategy(w_list)
  897. else:
  898. w_list.switch_to_object_strategy()
  899. w_list.append(w_item)
  900. def inplace_mul(self, w_list, times):
  901. self.switch_to_integer_strategy(w_list)
  902. w_list.inplace_mul(times)
  903. def deleteslice(self, w_list, start, step, slicelength):
  904. self.switch_to_integer_strategy(w_list)
  905. w_list.deleteslice(start, step, slicelength)
  906. def setitem(self, w_list, index, w_item):
  907. self.switch_to_integer_strategy(w_list)
  908. w_list.setitem(index, w_item)
  909. def setslice(self, w_list, start, step, slicelength, sequence_w):
  910. self.switch_to_integer_strategy(w_list)
  911. w_list.setslice(start, step, slicelength, sequence_w)
  912. def insert(self, w_list, index, w_item):
  913. self.switch_to_integer_strategy(w_list)
  914. w_list.insert(index, w_item)
  915. def extend(self, w_list, w_any):
  916. self.switch_to_integer_strategy(w_list)
  917. w_list.extend(w_any)
  918. def reverse(self, w_list):
  919. self.switch_to_integer_strategy(w_list)
  920. w_list.reverse()
  921. def sort(self, w_list, reverse):
  922. step = self.step(w_list)
  923. if step > 0 and reverse or step < 0 and not reverse:
  924. self.switch_to_integer_strategy(w_list)
  925. w_list.sort(reverse)
  926. class SimpleRangeListStrategy(BaseRangeListStrategy):
  927. """SimpleRangeListStrategy is used when a list is created using the range
  928. method providing only positive length. The storage is a one element tuple
  929. with positive integer storing length."""
  930. erase, unerase = rerased.new_erasing_pair("simple_range")
  931. erase = staticmethod(erase)
  932. unerase = staticmethod(unerase)
  933. def find(self, w_list, w_obj, startindex, stopindex):
  934. if type(w_obj) is W_IntObject:
  935. obj = self.unwrap(w_obj)
  936. length = self.unerase(w_list.lstorage)[0]
  937. if 0 <= obj < length and startindex <= obj < stopindex:
  938. return obj
  939. else:
  940. raise ValueError
  941. return ListStrategy.find(self, w_list, w_obj, startindex, stopindex)
  942. def length(self, w_list):
  943. return self.unerase(w_list.lstorage)[0]
  944. def step(self, w_list):
  945. return 1
  946. def _getitem_unwrapped(self, w_list, i):
  947. length = self.unerase(w_list.lstorage)[0]
  948. if i < 0:
  949. i += length
  950. if i < 0:
  951. raise IndexError
  952. elif i >= length:
  953. raise IndexError
  954. return i
  955. @specialize.arg(2)
  956. def _getitems_range(self, w_list, wrap_items):
  957. length = self.unerase(w_list.lstorage)[0]
  958. if wrap_items:
  959. r = [None] * length
  960. else:
  961. r = [0] * length
  962. i = 0
  963. while i < length:
  964. if wrap_items:
  965. r[i] = self.wrap(i)
  966. else:
  967. r[i] = i
  968. i += 1
  969. return r
  970. _getitems_range_unroll = jit.unroll_safe(
  971. func_with_new_name(_getitems_range, "_getitems_range_unroll"))
  972. def pop_end(self, w_list):
  973. new_length = self.unerase(w_list.lstorage)[0] - 1
  974. w_result = self.wrap(new_length)
  975. if new_length > 0:
  976. w_list.lstorage = self.erase((new_length,))
  977. else:
  978. strategy = w_list.strategy = self.space.fromcache(EmptyListStrategy)
  979. w_list.lstorage = strategy.erase(None)
  980. return w_result
  981. def pop(self, w_list, index):
  982. self.switch_to_integer_strategy(w_list)
  983. return w_list.pop(index)
  984. class RangeListStrategy(BaseRangeListStrategy):
  985. """RangeListStrategy is used when a list is created using the range method.
  986. The storage is a tuple containing only three integers start, step and
  987. length and elements are calculated based on these values. On any operation
  988. destroying the range (inserting, appending non-ints) the strategy is
  989. switched to IntegerListStrategy."""
  990. erase, unerase = rerased.new_erasing_pair("range")
  991. erase = staticmethod(erase)
  992. unerase = staticmethod(unerase)
  993. def find(self, w_list, w_obj, startindex, stopindex):
  994. if type(w_obj) is W_IntObject:
  995. obj = self.unwrap(w_obj)
  996. start, step, length = self.unerase(w_list.lstorage)
  997. if ((step > 0 and start <= obj <= start + (length - 1) * step and
  998. (start - obj) % step == 0) or
  999. (step < 0 and start + (length - 1) * step <= obj <= start and
  1000. (start - obj) % step == 0)):
  1001. index = (obj - start) // step
  1002. else:
  1003. raise ValueError
  1004. if startindex <= index < stopindex:
  1005. return index
  1006. raise ValueError
  1007. return ListStrategy.find(self, w_list, w_obj, startindex, stopindex)
  1008. def length(self, w_list):
  1009. return self.unerase(w_list.lstorage)[2]
  1010. def step(self, w_list):
  1011. return self.unerase(w_list.lstorage)[1]
  1012. def _getitem_unwrapped(self, w_list, i):
  1013. v = self.unerase(w_list.lstorage)
  1014. start = v[0]
  1015. step = v[1]
  1016. length = v[2]
  1017. if i < 0:
  1018. i += length
  1019. if i < 0:
  1020. raise IndexError
  1021. elif i >= length:
  1022. raise IndexError
  1023. return start + i * step
  1024. @specialize.arg(2)
  1025. def _getitems_range(self, w_list, wrap_items):
  1026. l = self.unerase(w_list.lstorage)
  1027. start = l[0]
  1028. step = l[1]
  1029. length = l[2]
  1030. if wrap_items:
  1031. r = [None] * length
  1032. else:
  1033. r = [0] * length
  1034. i = start
  1035. n = 0
  1036. while n < length:
  1037. if wrap_items:
  1038. r[n] = self.wrap(i)
  1039. else:
  1040. r[n] = i
  1041. i += step
  1042. n += 1
  1043. return r
  1044. _getitems_range_unroll = jit.unroll_safe(
  1045. func_with_new_name(_getitems_range, "_getitems_range_unroll"))
  1046. def pop_end(self, w_list):
  1047. start, step, length = self.unerase(w_list.lstorage)
  1048. w_result = self.wrap(start + (length - 1) * step)
  1049. new = self.erase((start, step, length - 1))
  1050. w_list.lstorage = new
  1051. return w_result
  1052. def pop(self, w_list, index):
  1053. l = self.unerase(w_list.lstorage)
  1054. start = l[0]
  1055. step = l[1]
  1056. length = l[2]
  1057. if index == 0:
  1058. w_result = self.wrap(start)
  1059. new = self.erase((start + step, step, length - 1))
  1060. w_list.lstorage = new
  1061. return w_result
  1062. elif index == length - 1:
  1063. return self.pop_end(w_list)
  1064. else:
  1065. self.switch_to_integer_strategy(w_list)
  1066. return w_list.pop(index)
  1067. class AbstractUnwrappedStrategy(object):
  1068. def wrap(self, unwrapped):
  1069. raise NotImplementedError
  1070. def unwrap(self, wrapped):
  1071. raise NotImplementedError
  1072. @staticmethod
  1073. def unerase(storage):
  1074. raise NotImplementedError("abstract base class")
  1075. @staticmethod
  1076. def erase(obj):
  1077. raise NotImplementedError("abstract base class")
  1078. def is_correct_type(self, w_obj):
  1079. raise NotImplementedError("abstract base class")
  1080. def list_is_correct_type(self, w_list):
  1081. raise NotImplementedError("abstract base class")
  1082. @jit.look_inside_iff(lambda space, w_list, list_w:
  1083. jit.loop_unrolling_heuristic(list_w, len(list_w), UNROLL_CUTOFF))
  1084. def init_from_list_w(self, w_list, list_w):
  1085. l = [self.unwrap(w_item) for w_item in list_w]
  1086. w_list.lstorage = self.erase(l)
  1087. def get_empty_storage(self, sizehint):
  1088. if sizehint == -1:
  1089. return self.erase([])
  1090. return self.erase(newlist_hint(sizehint))
  1091. def clone(self, w_list):
  1092. l = self.unerase(w_list.lstorage)
  1093. storage = self.erase(l[:])
  1094. w_clone = W_ListObject.from_storage_and_strategy(
  1095. self.space, storage, self)
  1096. return w_clone
  1097. def _resize_hint(self, w_list, hint):
  1098. resizelist_hint(self.unerase(w_list.lstorage), hint)
  1099. def copy_into(self, w_list, w_other):
  1100. w_other.strategy = self
  1101. items = self.unerase(w_list.lstorage)[:]
  1102. w_other.lstorage = self.erase(items)
  1103. def find(self, w_list, w_obj, start, stop):
  1104. if self.is_correct_type(w_obj):
  1105. return self._safe_find(w_list, self.unwrap(w_obj), start, stop)
  1106. return ListStrategy.find(self, w_list, w_obj, start, stop)
  1107. def _safe_find(self, w_list, obj, start, stop):
  1108. l = self.unerase(w_list.lstorage)
  1109. for i in range(start, min(stop, len(l))):
  1110. val = l[i]
  1111. if val == obj:
  1112. return i
  1113. raise ValueError
  1114. def length(self, w_list):
  1115. return len(self.unerase(w_list.lstorage))
  1116. def getitem(self, w_list, index):
  1117. l = self.unerase(w_list.lstorage)
  1118. try:
  1119. r = l[index]
  1120. except IndexError: # make RPython raise the exception
  1121. raise
  1122. return self.wrap(r)
  1123. @jit.look_inside_iff(lambda self, w_list:
  1124. jit.loop_unrolling_heuristic(w_list, w_list.length(),
  1125. UNROLL_CUTOFF))
  1126. def getitems_copy(self, w_list):
  1127. return [self.wrap(item) for item in self.unerase(w_list.lstorage)]
  1128. @jit.unroll_safe
  1129. def getitems_unroll(self, w_list):
  1130. return [self.wrap(item) for item in self.unerase(w_list.lstorage)]
  1131. @jit.look_inside_iff(lambda self, w_list:
  1132. jit.loop_unrolling_heuristic(w_list, w_list.length(),
  1133. UNROLL_CUTOFF))
  1134. def getitems_fixedsize(self, w_list):
  1135. return self.getitems_unroll(w_list)
  1136. def getstorage_copy(self, w_list):
  1137. items = self.unerase(w_list.lstorage)[:]
  1138. return self.erase(items)
  1139. def getslice(self, w_list, start, stop, step, length):
  1140. if step == 1 and 0 <= start <= stop:
  1141. l = self.unerase(w_list.lstorage)
  1142. assert start >= 0
  1143. assert stop >= 0
  1144. sublist = l[start:stop]
  1145. storage = self.erase(sublist)
  1146. return W_ListObject.from_storage_and_strategy(
  1147. self.space, storage, self)
  1148. else:
  1149. subitems_w = [self._none_value] * length
  1150. l = self.unerase(w_list.lstorage)
  1151. self._fill_in_with_sliced_items(subitems_w, l, start, step, length)
  1152. storage = self.erase(

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