PageRenderTime 56ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/pypy/rpython/rlist.py

https://bitbucket.org/pypy/pypy/
Python | 1060 lines | 860 code | 127 blank | 73 comment | 182 complexity | 972adfcf396502c6651d079242a5624e MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from pypy.tool.pairtype import pairtype, pair
  2. from pypy.objspace.flow.model import Constant
  3. from pypy.annotation import model as annmodel
  4. from pypy.rpython.error import TyperError
  5. from pypy.rpython.rmodel import Repr, IteratorRepr, IntegerRepr
  6. from pypy.rpython.rstr import AbstractStringRepr, AbstractCharRepr
  7. from pypy.rpython.lltypesystem.lltype import typeOf, Ptr, Void, Signed, Bool
  8. from pypy.rpython.lltypesystem.lltype import nullptr, Char, UniChar, Number
  9. from pypy.rpython import robject
  10. from pypy.rlib.objectmodel import malloc_zero_filled
  11. from pypy.rlib.debug import ll_assert
  12. from pypy.rlib.rarithmetic import ovfcheck, widen, r_uint, intmask
  13. from pypy.rpython.annlowlevel import ADTInterface
  14. from pypy.rlib import rgc, jit
  15. ADTIFixedList = ADTInterface(None, {
  16. 'll_newlist': (['SELF', Signed ], 'self'),
  17. 'll_length': (['self' ], Signed),
  18. 'll_getitem_fast': (['self', Signed ], 'item'),
  19. 'll_setitem_fast': (['self', Signed, 'item'], Void),
  20. })
  21. ADTIList = ADTInterface(ADTIFixedList, {
  22. '_ll_resize_ge': (['self', Signed ], Void),
  23. '_ll_resize_le': (['self', Signed ], Void),
  24. '_ll_resize': (['self', Signed ], Void),
  25. })
  26. def dum_checkidx(): pass
  27. def dum_nocheck(): pass
  28. class __extend__(annmodel.SomeList):
  29. def rtyper_makerepr(self, rtyper):
  30. listitem = self.listdef.listitem
  31. s_value = listitem.s_value
  32. if (listitem.range_step is not None and not listitem.mutated and
  33. not isinstance(s_value, annmodel.SomeImpossibleValue)):
  34. return rtyper.type_system.rrange.RangeRepr(listitem.range_step)
  35. elif (s_value.__class__ is annmodel.SomeObject and s_value.knowntype == object):
  36. return robject.pyobj_repr
  37. else:
  38. # cannot do the rtyper.getrepr() call immediately, for the case
  39. # of recursive structures -- i.e. if the listdef contains itself
  40. rlist = rtyper.type_system.rlist
  41. item_repr = lambda: rtyper.getrepr(listitem.s_value)
  42. known_maxlength = getattr(self, 'known_maxlength', False)
  43. if self.listdef.listitem.resized:
  44. return rlist.ListRepr(rtyper, item_repr, listitem, known_maxlength)
  45. else:
  46. return rlist.FixedSizeListRepr(rtyper, item_repr, listitem)
  47. def rtyper_makekey(self):
  48. self.listdef.listitem.dont_change_any_more = True
  49. known_maxlength = getattr(self, 'known_maxlength', False)
  50. return self.__class__, self.listdef.listitem, known_maxlength
  51. class AbstractBaseListRepr(Repr):
  52. eq_func_cache = None
  53. def recast(self, llops, v):
  54. return llops.convertvar(v, self.item_repr, self.external_item_repr)
  55. def convert_const(self, listobj):
  56. # get object from bound list method
  57. if listobj is None:
  58. return self.null_const()
  59. if not isinstance(listobj, list):
  60. raise TyperError("expected a list: %r" % (listobj,))
  61. try:
  62. key = Constant(listobj)
  63. return self.list_cache[key]
  64. except KeyError:
  65. self.setup()
  66. n = len(listobj)
  67. result = self.prepare_const(n)
  68. self.list_cache[key] = result
  69. r_item = self.item_repr
  70. if r_item.lowleveltype is not Void:
  71. for i in range(n):
  72. x = listobj[i]
  73. result.ll_setitem_fast(i, r_item.convert_const(x))
  74. return result
  75. def null_const(self):
  76. raise NotImplementedError
  77. def prepare_const(self, nitems):
  78. raise NotImplementedError
  79. def ll_str(self, l):
  80. constant = self.rstr_ll.ll_constant
  81. start = self.rstr_ll.ll_build_start
  82. push = self.rstr_ll.ll_build_push
  83. finish = self.rstr_ll.ll_build_finish
  84. length = l.ll_length()
  85. if length == 0:
  86. return constant("[]")
  87. buf = start(2 * length + 1)
  88. push(buf, constant("["), 0)
  89. item_repr = self.item_repr
  90. i = 0
  91. while i < length:
  92. if i > 0:
  93. push(buf, constant(", "), 2 * i)
  94. item = l.ll_getitem_fast(i)
  95. push(buf, item_repr.ll_str(item), 2 * i + 1)
  96. i += 1
  97. push(buf, constant("]"), 2 * length)
  98. return finish(buf)
  99. def rtype_bltn_list(self, hop):
  100. v_lst = hop.inputarg(self, 0)
  101. cRESLIST = hop.inputconst(Void, hop.r_result.LIST)
  102. return hop.gendirectcall(ll_copy, cRESLIST, v_lst)
  103. def rtype_len(self, hop):
  104. v_lst, = hop.inputargs(self)
  105. if hop.args_s[0].listdef.listitem.resized:
  106. ll_func = ll_len
  107. else:
  108. ll_func = ll_len_foldable
  109. return hop.gendirectcall(ll_func, v_lst)
  110. def rtype_is_true(self, hop):
  111. v_lst, = hop.inputargs(self)
  112. if hop.args_s[0].listdef.listitem.resized:
  113. ll_func = ll_list_is_true
  114. else:
  115. ll_func = ll_list_is_true_foldable
  116. return hop.gendirectcall(ll_func, v_lst)
  117. def rtype_method_reverse(self, hop):
  118. v_lst, = hop.inputargs(self)
  119. hop.exception_cannot_occur()
  120. hop.gendirectcall(ll_reverse,v_lst)
  121. def rtype_method_remove(self, hop):
  122. v_lst, v_value = hop.inputargs(self, self.item_repr)
  123. hop.has_implicit_exception(ValueError) # record that we know about it
  124. hop.exception_is_here()
  125. return hop.gendirectcall(ll_listremove, v_lst, v_value,
  126. self.get_eqfunc())
  127. def rtype_method_index(self, hop):
  128. v_lst, v_value = hop.inputargs(self, self.item_repr)
  129. hop.has_implicit_exception(ValueError) # record that we know about it
  130. hop.exception_is_here()
  131. return hop.gendirectcall(ll_listindex, v_lst, v_value, self.get_eqfunc())
  132. def get_ll_eq_function(self):
  133. result = self.eq_func_cache
  134. if result is not None:
  135. return result
  136. def list_eq(l1, l2):
  137. return ll_listeq(l1, l2, item_eq_func)
  138. self.eq_func_cache = list_eq
  139. # ^^^ do this first, before item_repr.get_ll_eq_function()
  140. item_eq_func = self.item_repr.get_ll_eq_function()
  141. return list_eq
  142. def _get_v_maxlength(self, hop):
  143. from pypy.rpython.rint import signed_repr
  144. v_iterable = hop.args_v[1]
  145. s_iterable = hop.args_s[1]
  146. r_iterable = hop.args_r[1]
  147. hop2 = hop.copy()
  148. while hop2.nb_args > 0:
  149. hop2.r_s_popfirstarg()
  150. hop2.v_s_insertfirstarg(v_iterable, s_iterable)
  151. hop2.r_result = signed_repr
  152. v_maxlength = r_iterable.rtype_len(hop2)
  153. return v_maxlength
  154. class AbstractListRepr(AbstractBaseListRepr):
  155. def rtype_method_append(self, hop):
  156. v_lst, v_value = hop.inputargs(self, self.item_repr)
  157. hop.exception_cannot_occur()
  158. hop.gendirectcall(ll_append, v_lst, v_value)
  159. def rtype_method_insert(self, hop):
  160. v_lst, v_index, v_value = hop.inputargs(self, Signed, self.item_repr)
  161. arg1 = hop.args_s[1]
  162. args = v_lst, v_index, v_value
  163. if arg1.is_constant() and arg1.const == 0:
  164. llfn = ll_prepend
  165. args = v_lst, v_value
  166. elif arg1.nonneg:
  167. llfn = ll_insert_nonneg
  168. else:
  169. raise TyperError("insert() index must be proven non-negative")
  170. hop.exception_cannot_occur()
  171. hop.gendirectcall(llfn, *args)
  172. def rtype_method_extend(self, hop):
  173. v_lst1, v_lst2 = hop.inputargs(*hop.args_r)
  174. hop.exception_cannot_occur()
  175. hop.gendirectcall(ll_extend, v_lst1, v_lst2)
  176. def rtype_method_pop(self, hop):
  177. if hop.has_implicit_exception(IndexError):
  178. spec = dum_checkidx
  179. else:
  180. spec = dum_nocheck
  181. v_func = hop.inputconst(Void, spec)
  182. if hop.nb_args == 2:
  183. args = hop.inputargs(self, Signed)
  184. assert hasattr(args[1], 'concretetype')
  185. arg1 = hop.args_s[1]
  186. if arg1.is_constant() and arg1.const == 0:
  187. llfn = ll_pop_zero
  188. args = args[:1]
  189. elif hop.args_s[1].nonneg:
  190. llfn = ll_pop_nonneg
  191. else:
  192. llfn = ll_pop
  193. else:
  194. args = hop.inputargs(self)
  195. llfn = ll_pop_default
  196. hop.exception_is_here()
  197. v_res = hop.gendirectcall(llfn, v_func, *args)
  198. return self.recast(hop.llops, v_res)
  199. class AbstractFixedSizeListRepr(AbstractBaseListRepr):
  200. pass
  201. class __extend__(pairtype(AbstractBaseListRepr, Repr)):
  202. def rtype_contains((r_lst, _), hop):
  203. v_lst, v_any = hop.inputargs(r_lst, r_lst.item_repr)
  204. hop.exception_cannot_occur()
  205. return hop.gendirectcall(ll_listcontains, v_lst, v_any, r_lst.get_eqfunc())
  206. class __extend__(pairtype(AbstractBaseListRepr, IntegerRepr)):
  207. def rtype_getitem((r_lst, r_int), hop, checkidx=False):
  208. v_lst, v_index = hop.inputargs(r_lst, Signed)
  209. if checkidx:
  210. hop.exception_is_here()
  211. else:
  212. hop.exception_cannot_occur()
  213. if hop.args_s[0].listdef.listitem.mutated or checkidx:
  214. if hop.args_s[1].nonneg:
  215. llfn = ll_getitem_nonneg
  216. else:
  217. llfn = ll_getitem
  218. if checkidx:
  219. spec = dum_checkidx
  220. else:
  221. spec = dum_nocheck
  222. c_func_marker = hop.inputconst(Void, spec)
  223. v_res = hop.gendirectcall(llfn, c_func_marker, v_lst, v_index)
  224. else:
  225. # this is the 'foldable' version, which is not used when
  226. # we check for IndexError
  227. if hop.args_s[1].nonneg:
  228. llfn = ll_getitem_foldable_nonneg
  229. else:
  230. llfn = ll_getitem_foldable
  231. v_res = hop.gendirectcall(llfn, v_lst, v_index)
  232. return r_lst.recast(hop.llops, v_res)
  233. rtype_getitem_key = rtype_getitem
  234. def rtype_getitem_idx((r_lst, r_int), hop):
  235. return pair(r_lst, r_int).rtype_getitem(hop, checkidx=True)
  236. rtype_getitem_idx_key = rtype_getitem_idx
  237. def rtype_setitem((r_lst, r_int), hop):
  238. if hop.has_implicit_exception(IndexError):
  239. spec = dum_checkidx
  240. else:
  241. spec = dum_nocheck
  242. v_func = hop.inputconst(Void, spec)
  243. v_lst, v_index, v_item = hop.inputargs(r_lst, Signed, r_lst.item_repr)
  244. if hop.args_s[1].nonneg:
  245. llfn = ll_setitem_nonneg
  246. else:
  247. llfn = ll_setitem
  248. hop.exception_is_here()
  249. return hop.gendirectcall(llfn, v_func, v_lst, v_index, v_item)
  250. def rtype_mul((r_lst, r_int), hop):
  251. cRESLIST = hop.inputconst(Void, hop.r_result.LIST)
  252. v_lst, v_factor = hop.inputargs(r_lst, Signed)
  253. return hop.gendirectcall(ll_mul, cRESLIST, v_lst, v_factor)
  254. class __extend__(pairtype(AbstractListRepr, IntegerRepr)):
  255. def rtype_delitem((r_lst, r_int), hop):
  256. if hop.has_implicit_exception(IndexError):
  257. spec = dum_checkidx
  258. else:
  259. spec = dum_nocheck
  260. v_func = hop.inputconst(Void, spec)
  261. v_lst, v_index = hop.inputargs(r_lst, Signed)
  262. if hop.args_s[1].nonneg:
  263. llfn = ll_delitem_nonneg
  264. else:
  265. llfn = ll_delitem
  266. hop.exception_is_here()
  267. return hop.gendirectcall(llfn, v_func, v_lst, v_index)
  268. def rtype_inplace_mul((r_lst, r_int), hop):
  269. v_lst, v_factor = hop.inputargs(r_lst, Signed)
  270. return hop.gendirectcall(ll_inplace_mul, v_lst, v_factor)
  271. class __extend__(pairtype(AbstractBaseListRepr, AbstractBaseListRepr)):
  272. def convert_from_to((r_lst1, r_lst2), v, llops):
  273. if r_lst1.listitem is None or r_lst2.listitem is None:
  274. return NotImplemented
  275. if r_lst1.listitem is not r_lst2.listitem:
  276. return NotImplemented
  277. return v
  278. ## # TODO: move it to lltypesystem
  279. ## def rtype_is_((r_lst1, r_lst2), hop):
  280. ## if r_lst1.lowleveltype != r_lst2.lowleveltype:
  281. ## # obscure logic, the is can be true only if both are None
  282. ## v_lst1, v_lst2 = hop.inputargs(r_lst1, r_lst2)
  283. ## return hop.gendirectcall(ll_both_none, v_lst1, v_lst2)
  284. ## return pairtype(Repr, Repr).rtype_is_(pair(r_lst1, r_lst2), hop)
  285. def rtype_eq((r_lst1, r_lst2), hop):
  286. assert r_lst1.item_repr == r_lst2.item_repr
  287. v_lst1, v_lst2 = hop.inputargs(r_lst1, r_lst2)
  288. return hop.gendirectcall(ll_listeq, v_lst1, v_lst2, r_lst1.get_eqfunc())
  289. def rtype_ne((r_lst1, r_lst2), hop):
  290. assert r_lst1.item_repr == r_lst2.item_repr
  291. v_lst1, v_lst2 = hop.inputargs(r_lst1, r_lst2)
  292. flag = hop.gendirectcall(ll_listeq, v_lst1, v_lst2, r_lst1.get_eqfunc())
  293. return hop.genop('bool_not', [flag], resulttype=Bool)
  294. def rtype_newlist(hop, v_sizehint=None):
  295. nb_args = hop.nb_args
  296. r_list = hop.r_result
  297. if r_list == robject.pyobj_repr: # special case: SomeObject lists!
  298. clist = hop.inputconst(robject.pyobj_repr, list)
  299. v_result = hop.genop('simple_call', [clist], resulttype = robject.pyobj_repr)
  300. cname = hop.inputconst(robject.pyobj_repr, 'append')
  301. v_meth = hop.genop('getattr', [v_result, cname], resulttype = robject.pyobj_repr)
  302. for i in range(nb_args):
  303. v_item = hop.inputarg(robject.pyobj_repr, arg=i)
  304. hop.genop('simple_call', [v_meth, v_item], resulttype = robject.pyobj_repr)
  305. return v_result
  306. r_listitem = r_list.item_repr
  307. items_v = [hop.inputarg(r_listitem, arg=i) for i in range(nb_args)]
  308. return hop.rtyper.type_system.rlist.newlist(hop.llops, r_list, items_v,
  309. v_sizehint=v_sizehint)
  310. def rtype_alloc_and_set(hop):
  311. r_list = hop.r_result
  312. v_count, v_item = hop.inputargs(Signed, r_list.item_repr)
  313. cLIST = hop.inputconst(Void, r_list.LIST)
  314. return hop.gendirectcall(ll_alloc_and_set, cLIST, v_count, v_item)
  315. class __extend__(pairtype(AbstractBaseListRepr, AbstractBaseListRepr)):
  316. def rtype_add((r_lst1, r_lst2), hop):
  317. v_lst1, v_lst2 = hop.inputargs(r_lst1, r_lst2)
  318. cRESLIST = hop.inputconst(Void, hop.r_result.LIST)
  319. return hop.gendirectcall(ll_concat, cRESLIST, v_lst1, v_lst2)
  320. class __extend__(pairtype(AbstractListRepr, AbstractBaseListRepr)):
  321. def rtype_inplace_add((r_lst1, r_lst2), hop):
  322. v_lst1, v_lst2 = hop.inputargs(r_lst1, r_lst2)
  323. hop.gendirectcall(ll_extend, v_lst1, v_lst2)
  324. return v_lst1
  325. class __extend__(pairtype(AbstractListRepr, AbstractStringRepr)):
  326. def rtype_inplace_add((r_lst1, r_str2), hop):
  327. if r_lst1.item_repr.lowleveltype not in (Char, UniChar):
  328. raise TyperError('"lst += string" only supported with a list '
  329. 'of chars or unichars')
  330. string_repr = r_str2.repr
  331. v_lst1, v_str2 = hop.inputargs(r_lst1, string_repr)
  332. c_strlen = hop.inputconst(Void, string_repr.ll.ll_strlen)
  333. c_stritem = hop.inputconst(Void, string_repr.ll.ll_stritem_nonneg)
  334. hop.gendirectcall(ll_extend_with_str, v_lst1, v_str2,
  335. c_strlen, c_stritem)
  336. return v_lst1
  337. def rtype_extend_with_str_slice((r_lst1, r_str2), hop):
  338. if r_lst1.item_repr.lowleveltype not in (Char, UniChar):
  339. raise TyperError('"lst += string" only supported with a list '
  340. 'of chars or unichars')
  341. string_repr = r_lst1.rtyper.type_system.rstr.string_repr
  342. v_lst1 = hop.inputarg(r_lst1, arg=0)
  343. v_str2 = hop.inputarg(string_repr, arg=3)
  344. kind, vlist = hop.decompose_slice_args()
  345. c_strlen = hop.inputconst(Void, string_repr.ll.ll_strlen)
  346. c_stritem = hop.inputconst(Void, string_repr.ll.ll_stritem_nonneg)
  347. ll_fn = globals()['ll_extend_with_str_slice_%s' % kind]
  348. hop.gendirectcall(ll_fn, v_lst1, v_str2, c_strlen, c_stritem, *vlist)
  349. return v_lst1
  350. class __extend__(pairtype(AbstractListRepr, AbstractCharRepr)):
  351. def rtype_extend_with_char_count((r_lst1, r_chr2), hop):
  352. if r_lst1.item_repr.lowleveltype not in (Char, UniChar):
  353. raise TyperError('"lst += string" only supported with a list '
  354. 'of chars or unichars')
  355. char_repr = r_lst1.rtyper.type_system.rstr.char_repr
  356. v_lst1, v_chr, v_count = hop.inputargs(r_lst1, char_repr, Signed)
  357. hop.gendirectcall(ll_extend_with_char_count, v_lst1, v_chr, v_count)
  358. return v_lst1
  359. class __extend__(AbstractBaseListRepr):
  360. def rtype_getslice(r_lst, hop):
  361. cRESLIST = hop.inputconst(Void, hop.r_result.LIST)
  362. v_lst = hop.inputarg(r_lst, arg=0)
  363. kind, vlist = hop.decompose_slice_args()
  364. ll_listslice = globals()['ll_listslice_%s' % kind]
  365. return hop.gendirectcall(ll_listslice, cRESLIST, v_lst, *vlist)
  366. def rtype_setslice(r_lst, hop):
  367. v_lst = hop.inputarg(r_lst, arg=0)
  368. kind, vlist = hop.decompose_slice_args()
  369. if kind != 'startstop':
  370. raise TyperError('list.setitem does not support %r slices' % (
  371. kind,))
  372. v_start, v_stop = vlist
  373. v_lst2 = hop.inputarg(hop.args_r[3], arg=3)
  374. hop.gendirectcall(ll_listsetslice, v_lst, v_start, v_stop, v_lst2)
  375. def rtype_delslice(r_lst, hop):
  376. v_lst = hop.inputarg(r_lst, arg=0)
  377. kind, vlist = hop.decompose_slice_args()
  378. ll_listdelslice = globals()['ll_listdelslice_%s' % kind]
  379. return hop.gendirectcall(ll_listdelslice, v_lst, *vlist)
  380. # ____________________________________________________________
  381. #
  382. # Iteration.
  383. class AbstractListIteratorRepr(IteratorRepr):
  384. def newiter(self, hop):
  385. v_lst, = hop.inputargs(self.r_list)
  386. citerptr = hop.inputconst(Void, self.lowleveltype)
  387. return hop.gendirectcall(self.ll_listiter, citerptr, v_lst)
  388. def rtype_next(self, hop):
  389. v_iter, = hop.inputargs(self)
  390. hop.has_implicit_exception(StopIteration) # record that we know about it
  391. hop.exception_is_here()
  392. v_res = hop.gendirectcall(self.ll_listnext, v_iter)
  393. return self.r_list.recast(hop.llops, v_res)
  394. # ____________________________________________________________
  395. #
  396. # Low-level methods. These can be run for testing, but are meant to
  397. # be direct_call'ed from rtyped flow graphs, which means that they will
  398. # get flowed and annotated, mostly with SomePtr.
  399. #
  400. # === a note about overflows ===
  401. #
  402. # The maximal length of RPython lists is bounded by the assumption that
  403. # we can never allocate arrays more than sys.maxint bytes in size.
  404. # Our arrays have a length and some GC headers, so a list of characters
  405. # could come near sys.maxint in length (but not reach it). A list of
  406. # pointers could only come near sys.maxint/sizeof(void*) elements. There
  407. # is the list of Voids that could reach exactly sys.maxint elements,
  408. # but for now let's ignore this case -- the reasoning is that even if
  409. # the length of a Void list overflows, nothing bad memory-wise can be
  410. # done with it. So in the sequel we don't bother checking for overflow
  411. # when we compute "ll_length() + 1".
  412. def ll_alloc_and_set(LIST, count, item):
  413. if count < 0:
  414. count = 0
  415. l = LIST.ll_newlist(count)
  416. T = typeOf(item)
  417. if T is Char or T is UniChar:
  418. check = ord(item)
  419. elif isinstance(T, Number):
  420. check = widen(item)
  421. else:
  422. check = item
  423. if (not malloc_zero_filled) or check: # as long as malloc it is known to zero the allocated memory avoid zeroing twice
  424. i = 0
  425. while i < count:
  426. l.ll_setitem_fast(i, item)
  427. i += 1
  428. return l
  429. ll_alloc_and_set.oopspec = 'newlist(count, item)'
  430. # return a nullptr() if lst is a list of pointers it, else None. Note
  431. # that if we are using ootypesystem there are not pointers, so we
  432. # always return None.
  433. def ll_null_item(lst):
  434. LIST = typeOf(lst)
  435. if isinstance(LIST, Ptr):
  436. ITEM = LIST.TO.ITEM
  437. if isinstance(ITEM, Ptr):
  438. return nullptr(ITEM.TO)
  439. return None
  440. def listItemType(lst):
  441. LIST = typeOf(lst)
  442. if isinstance(LIST, Ptr): # lltype
  443. LIST = LIST.TO
  444. return LIST.ITEM
  445. def ll_arraycopy(source, dest, source_start, dest_start, length):
  446. SRCTYPE = typeOf(source)
  447. if isinstance(SRCTYPE, Ptr):
  448. # lltype
  449. rgc.ll_arraycopy(source.ll_items(), dest.ll_items(),
  450. source_start, dest_start, length)
  451. else:
  452. # ootype -- XXX improve the case of array->array copy?
  453. i = 0
  454. while i < length:
  455. item = source.ll_getitem_fast(source_start + i)
  456. dest.ll_setitem_fast(dest_start + i, item)
  457. i += 1
  458. ll_arraycopy._annenforceargs_ = [None, None, int, int, int]
  459. # no oopspec -- the function is inlined by the JIT
  460. def ll_copy(RESLIST, l):
  461. length = l.ll_length()
  462. new_lst = RESLIST.ll_newlist(length)
  463. ll_arraycopy(l, new_lst, 0, 0, length)
  464. return new_lst
  465. # no oopspec -- the function is inlined by the JIT
  466. def ll_len(l):
  467. return l.ll_length()
  468. def ll_list_is_true(l):
  469. # check if a list is True, allowing for None
  470. return bool(l) and l.ll_length() != 0
  471. # no oopspec -- the function is inlined by the JIT
  472. def ll_len_foldable(l):
  473. return l.ll_length()
  474. ll_len_foldable.oopspec = 'list.len_foldable(l)'
  475. def ll_list_is_true_foldable(l):
  476. return bool(l) and ll_len_foldable(l) != 0
  477. # no oopspec -- the function is inlined by the JIT
  478. def ll_append(l, newitem):
  479. length = l.ll_length()
  480. l._ll_resize_ge(length+1) # see "a note about overflows" above
  481. l.ll_setitem_fast(length, newitem)
  482. # this one is for the special case of insert(0, x)
  483. def ll_prepend(l, newitem):
  484. length = l.ll_length()
  485. l._ll_resize_ge(length+1) # see "a note about overflows" above
  486. dst = length
  487. while dst > 0:
  488. src = dst - 1
  489. l.ll_setitem_fast(dst, l.ll_getitem_fast(src))
  490. dst = src
  491. l.ll_setitem_fast(0, newitem)
  492. ll_prepend.oopspec = 'list.insert(l, 0, newitem)'
  493. def ll_concat(RESLIST, l1, l2):
  494. len1 = l1.ll_length()
  495. len2 = l2.ll_length()
  496. try:
  497. newlength = ovfcheck(len1 + len2)
  498. except OverflowError:
  499. raise MemoryError
  500. l = RESLIST.ll_newlist(newlength)
  501. ll_arraycopy(l1, l, 0, 0, len1)
  502. ll_arraycopy(l2, l, 0, len1, len2)
  503. return l
  504. # no oopspec -- the function is inlined by the JIT
  505. def ll_insert_nonneg(l, index, newitem):
  506. length = l.ll_length()
  507. ll_assert(0 <= index, "negative list insertion index")
  508. ll_assert(index <= length, "list insertion index out of bound")
  509. l._ll_resize_ge(length+1) # see "a note about overflows" above
  510. dst = length
  511. while dst > index:
  512. src = dst - 1
  513. l.ll_setitem_fast(dst, l.ll_getitem_fast(src))
  514. dst = src
  515. l.ll_setitem_fast(index, newitem)
  516. ll_insert_nonneg.oopspec = 'list.insert(l, index, newitem)'
  517. def ll_pop_nonneg(func, l, index):
  518. ll_assert(index >= 0, "unexpectedly negative list pop index")
  519. if func is dum_checkidx:
  520. if index >= l.ll_length():
  521. raise IndexError
  522. else:
  523. ll_assert(index < l.ll_length(), "list pop index out of bound")
  524. res = l.ll_getitem_fast(index)
  525. ll_delitem_nonneg(dum_nocheck, l, index)
  526. return res
  527. ll_pop_nonneg.oopspec = 'list.pop(l, index)'
  528. def ll_pop_default(func, l):
  529. length = l.ll_length()
  530. if func is dum_checkidx and (length == 0):
  531. raise IndexError
  532. ll_assert(length > 0, "pop from empty list")
  533. index = length - 1
  534. newlength = index
  535. res = l.ll_getitem_fast(index)
  536. null = ll_null_item(l)
  537. if null is not None:
  538. l.ll_setitem_fast(index, null)
  539. l._ll_resize_le(newlength)
  540. return res
  541. def ll_pop_zero(func, l):
  542. length = l.ll_length()
  543. if func is dum_checkidx and (length == 0):
  544. raise IndexError
  545. ll_assert(length > 0, "pop(0) from empty list")
  546. newlength = length - 1
  547. res = l.ll_getitem_fast(0)
  548. j = 0
  549. j1 = j+1
  550. while j < newlength:
  551. l.ll_setitem_fast(j, l.ll_getitem_fast(j1))
  552. j = j1
  553. j1 += 1
  554. null = ll_null_item(l)
  555. if null is not None:
  556. l.ll_setitem_fast(newlength, null)
  557. l._ll_resize_le(newlength)
  558. return res
  559. ll_pop_zero.oopspec = 'list.pop(l, 0)'
  560. def ll_pop(func, l, index):
  561. length = l.ll_length()
  562. if index < 0:
  563. index += length
  564. if func is dum_checkidx:
  565. if index < 0 or index >= length:
  566. raise IndexError
  567. else:
  568. ll_assert(index >= 0, "negative list pop index out of bound")
  569. ll_assert(index < length, "list pop index out of bound")
  570. res = l.ll_getitem_fast(index)
  571. ll_delitem_nonneg(dum_nocheck, l, index)
  572. return res
  573. @jit.look_inside_iff(lambda l: jit.isvirtual(l))
  574. def ll_reverse(l):
  575. length = l.ll_length()
  576. i = 0
  577. length_1_i = length-1-i
  578. while i < length_1_i:
  579. tmp = l.ll_getitem_fast(i)
  580. l.ll_setitem_fast(i, l.ll_getitem_fast(length_1_i))
  581. l.ll_setitem_fast(length_1_i, tmp)
  582. i += 1
  583. length_1_i -= 1
  584. def ll_getitem_nonneg(func, l, index):
  585. ll_assert(index >= 0, "unexpectedly negative list getitem index")
  586. if func is dum_checkidx:
  587. if index >= l.ll_length():
  588. raise IndexError
  589. return l.ll_getitem_fast(index)
  590. ll_getitem_nonneg._always_inline_ = True
  591. # no oopspec -- the function is inlined by the JIT
  592. def ll_getitem(func, l, index):
  593. if func is dum_checkidx:
  594. length = l.ll_length() # common case: 0 <= index < length
  595. if r_uint(index) >= r_uint(length):
  596. # Failed, so either (-length <= index < 0), or we have to raise
  597. # IndexError. First add 'length' to get the final index, then
  598. # check that we now have (0 <= index < length).
  599. index = r_uint(index) + r_uint(length)
  600. if index >= r_uint(length):
  601. raise IndexError
  602. index = intmask(index)
  603. else:
  604. # We don't want checking, but still want to support index < 0.
  605. # Only call ll_length() if needed.
  606. if index < 0:
  607. index += l.ll_length()
  608. ll_assert(index >= 0, "negative list getitem index out of bound")
  609. return l.ll_getitem_fast(index)
  610. # no oopspec -- the function is inlined by the JIT
  611. def ll_getitem_foldable_nonneg(l, index):
  612. ll_assert(index >= 0, "unexpectedly negative list getitem index")
  613. return l.ll_getitem_fast(index)
  614. ll_getitem_foldable_nonneg.oopspec = 'list.getitem_foldable(l, index)'
  615. def ll_getitem_foldable(l, index):
  616. if index < 0:
  617. index += l.ll_length()
  618. return ll_getitem_foldable_nonneg(l, index)
  619. ll_getitem_foldable._always_inline_ = True
  620. # no oopspec -- the function is inlined by the JIT
  621. def ll_setitem_nonneg(func, l, index, newitem):
  622. ll_assert(index >= 0, "unexpectedly negative list setitem index")
  623. if func is dum_checkidx:
  624. if index >= l.ll_length():
  625. raise IndexError
  626. l.ll_setitem_fast(index, newitem)
  627. ll_setitem_nonneg._always_inline_ = True
  628. # no oopspec -- the function is inlined by the JIT
  629. def ll_setitem(func, l, index, newitem):
  630. if func is dum_checkidx:
  631. length = l.ll_length()
  632. if r_uint(index) >= r_uint(length): # see comments in ll_getitem().
  633. index = r_uint(index) + r_uint(length)
  634. if index >= r_uint(length):
  635. raise IndexError
  636. index = intmask(index)
  637. else:
  638. if index < 0:
  639. index += l.ll_length()
  640. ll_assert(index >= 0, "negative list setitem index out of bound")
  641. l.ll_setitem_fast(index, newitem)
  642. # no oopspec -- the function is inlined by the JIT
  643. def ll_delitem_nonneg(func, l, index):
  644. ll_assert(index >= 0, "unexpectedly negative list delitem index")
  645. length = l.ll_length()
  646. if func is dum_checkidx:
  647. if index >= length:
  648. raise IndexError
  649. else:
  650. ll_assert(index < length, "list delitem index out of bound")
  651. newlength = length - 1
  652. j = index
  653. j1 = j+1
  654. while j < newlength:
  655. l.ll_setitem_fast(j, l.ll_getitem_fast(j1))
  656. j = j1
  657. j1 += 1
  658. null = ll_null_item(l)
  659. if null is not None:
  660. l.ll_setitem_fast(newlength, null)
  661. l._ll_resize_le(newlength)
  662. ll_delitem_nonneg.oopspec = 'list.delitem(l, index)'
  663. def ll_delitem(func, l, index):
  664. if func is dum_checkidx:
  665. length = l.ll_length()
  666. if r_uint(index) >= r_uint(length): # see comments in ll_getitem().
  667. index = r_uint(index) + r_uint(length)
  668. if index >= r_uint(length):
  669. raise IndexError
  670. index = intmask(index)
  671. else:
  672. if index < 0:
  673. index += l.ll_length()
  674. ll_assert(index >= 0, "negative list delitem index out of bound")
  675. ll_delitem_nonneg(dum_nocheck, l, index)
  676. # no oopspec -- the function is inlined by the JIT
  677. def ll_extend(l1, l2):
  678. len1 = l1.ll_length()
  679. len2 = l2.ll_length()
  680. try:
  681. newlength = ovfcheck(len1 + len2)
  682. except OverflowError:
  683. raise MemoryError
  684. l1._ll_resize_ge(newlength)
  685. ll_arraycopy(l2, l1, 0, len1, len2)
  686. def ll_extend_with_str(lst, s, getstrlen, getstritem):
  687. return ll_extend_with_str_slice_startonly(lst, s, getstrlen, getstritem, 0)
  688. def ll_extend_with_str_slice_startonly(lst, s, getstrlen, getstritem, start):
  689. len1 = lst.ll_length()
  690. len2 = getstrlen(s)
  691. count2 = len2 - start
  692. ll_assert(start >= 0, "unexpectedly negative str slice start")
  693. assert count2 >= 0, "str slice start larger than str length"
  694. try:
  695. newlength = ovfcheck(len1 + count2)
  696. except OverflowError:
  697. raise MemoryError
  698. lst._ll_resize_ge(newlength)
  699. i = start
  700. j = len1
  701. while i < len2:
  702. c = getstritem(s, i)
  703. if listItemType(lst) is UniChar:
  704. c = unichr(ord(c))
  705. lst.ll_setitem_fast(j, c)
  706. i += 1
  707. j += 1
  708. # not inlined by the JIT -- contains a loop
  709. def ll_extend_with_str_slice_startstop(lst, s, getstrlen, getstritem,
  710. start, stop):
  711. len1 = lst.ll_length()
  712. len2 = getstrlen(s)
  713. ll_assert(start >= 0, "unexpectedly negative str slice start")
  714. ll_assert(start <= len2, "str slice start larger than str length")
  715. if stop > len2:
  716. stop = len2
  717. count2 = stop - start
  718. assert count2 >= 0, "str slice stop smaller than start"
  719. try:
  720. newlength = ovfcheck(len1 + count2)
  721. except OverflowError:
  722. raise MemoryError
  723. lst._ll_resize_ge(newlength)
  724. i = start
  725. j = len1
  726. while i < stop:
  727. c = getstritem(s, i)
  728. if listItemType(lst) is UniChar:
  729. c = unichr(ord(c))
  730. lst.ll_setitem_fast(j, c)
  731. i += 1
  732. j += 1
  733. # not inlined by the JIT -- contains a loop
  734. def ll_extend_with_str_slice_minusone(lst, s, getstrlen, getstritem):
  735. len1 = lst.ll_length()
  736. len2m1 = getstrlen(s) - 1
  737. assert len2m1 >= 0, "empty string is sliced with [:-1]"
  738. try:
  739. newlength = ovfcheck(len1 + len2m1)
  740. except OverflowError:
  741. raise MemoryError
  742. lst._ll_resize_ge(newlength)
  743. i = 0
  744. j = len1
  745. while i < len2m1:
  746. c = getstritem(s, i)
  747. if listItemType(lst) is UniChar:
  748. c = unichr(ord(c))
  749. lst.ll_setitem_fast(j, c)
  750. i += 1
  751. j += 1
  752. # not inlined by the JIT -- contains a loop
  753. def ll_extend_with_char_count(lst, char, count):
  754. if count <= 0:
  755. return
  756. len1 = lst.ll_length()
  757. try:
  758. newlength = ovfcheck(len1 + count)
  759. except OverflowError:
  760. raise MemoryError
  761. lst._ll_resize_ge(newlength)
  762. j = len1
  763. if listItemType(lst) is UniChar:
  764. char = unichr(ord(char))
  765. while j < newlength:
  766. lst.ll_setitem_fast(j, char)
  767. j += 1
  768. # not inlined by the JIT -- contains a loop
  769. def ll_listslice_startonly(RESLIST, l1, start):
  770. len1 = l1.ll_length()
  771. ll_assert(start >= 0, "unexpectedly negative list slice start")
  772. ll_assert(start <= len1, "list slice start larger than list length")
  773. newlength = len1 - start
  774. l = RESLIST.ll_newlist(newlength)
  775. ll_arraycopy(l1, l, start, 0, newlength)
  776. return l
  777. ll_listslice_startonly._annenforceargs_ = (None, None, int)
  778. # no oopspec -- the function is inlined by the JIT
  779. def ll_listslice_startstop(RESLIST, l1, start, stop):
  780. length = l1.ll_length()
  781. ll_assert(start >= 0, "unexpectedly negative list slice start")
  782. ll_assert(start <= length, "list slice start larger than list length")
  783. ll_assert(stop >= start, "list slice stop smaller than start")
  784. if stop > length:
  785. stop = length
  786. newlength = stop - start
  787. l = RESLIST.ll_newlist(newlength)
  788. ll_arraycopy(l1, l, start, 0, newlength)
  789. return l
  790. # no oopspec -- the function is inlined by the JIT
  791. def ll_listslice_minusone(RESLIST, l1):
  792. newlength = l1.ll_length() - 1
  793. ll_assert(newlength >= 0, "empty list is sliced with [:-1]")
  794. l = RESLIST.ll_newlist(newlength)
  795. ll_arraycopy(l1, l, 0, 0, newlength)
  796. return l
  797. # no oopspec -- the function is inlined by the JIT
  798. @jit.look_inside_iff(lambda l, start: jit.isconstant(start) and jit.isvirtual(l))
  799. @jit.oopspec('list.delslice_startonly(l, start)')
  800. def ll_listdelslice_startonly(l, start):
  801. ll_assert(start >= 0, "del l[start:] with unexpectedly negative start")
  802. ll_assert(start <= l.ll_length(), "del l[start:] with start > len(l)")
  803. newlength = start
  804. null = ll_null_item(l)
  805. if null is not None:
  806. j = l.ll_length() - 1
  807. while j >= newlength:
  808. l.ll_setitem_fast(j, null)
  809. j -= 1
  810. l._ll_resize_le(newlength)
  811. def ll_listdelslice_startstop(l, start, stop):
  812. length = l.ll_length()
  813. ll_assert(start >= 0, "del l[start:x] with unexpectedly negative start")
  814. ll_assert(start <= length, "del l[start:x] with start > len(l)")
  815. ll_assert(stop >= start, "del l[x:y] with x > y")
  816. if stop > length:
  817. stop = length
  818. newlength = length - (stop-start)
  819. j = start
  820. i = stop
  821. while j < newlength:
  822. l.ll_setitem_fast(j, l.ll_getitem_fast(i))
  823. i += 1
  824. j += 1
  825. null = ll_null_item(l)
  826. if null is not None:
  827. j = length - 1
  828. while j >= newlength:
  829. l.ll_setitem_fast(j, null)
  830. j -= 1
  831. l._ll_resize_le(newlength)
  832. ll_listdelslice_startstop.oopspec = 'list.delslice_startstop(l, start, stop)'
  833. def ll_listsetslice(l1, start, stop, l2):
  834. count = l2.ll_length()
  835. ll_assert(start >= 0, "l[start:x] = l with unexpectedly negative start")
  836. ll_assert(start <= l1.ll_length(), "l[start:x] = l with start > len(l)")
  837. ll_assert(count == stop - start,
  838. "setslice cannot resize lists in RPython")
  839. # XXX ...but it would be easy enough to support if really needed
  840. ll_arraycopy(l2, l1, 0, start, count)
  841. ll_listsetslice.oopspec = 'list.setslice(l1, start, stop, l2)'
  842. # ____________________________________________________________
  843. #
  844. # Comparison.
  845. def ll_listeq(l1, l2, eqfn):
  846. if not l1 and not l2:
  847. return True
  848. if not l1 or not l2:
  849. return False
  850. len1 = l1.ll_length()
  851. len2 = l2.ll_length()
  852. if len1 != len2:
  853. return False
  854. j = 0
  855. while j < len1:
  856. if eqfn is None:
  857. if l1.ll_getitem_fast(j) != l2.ll_getitem_fast(j):
  858. return False
  859. else:
  860. if not eqfn(l1.ll_getitem_fast(j), l2.ll_getitem_fast(j)):
  861. return False
  862. j += 1
  863. return True
  864. # not inlined by the JIT -- contains a loop
  865. def ll_listcontains(lst, obj, eqfn):
  866. lng = lst.ll_length()
  867. j = 0
  868. while j < lng:
  869. if eqfn is None:
  870. if lst.ll_getitem_fast(j) == obj:
  871. return True
  872. else:
  873. if eqfn(lst.ll_getitem_fast(j), obj):
  874. return True
  875. j += 1
  876. return False
  877. # not inlined by the JIT -- contains a loop
  878. def ll_listindex(lst, obj, eqfn):
  879. lng = lst.ll_length()
  880. j = 0
  881. while j < lng:
  882. if eqfn is None:
  883. if lst.ll_getitem_fast(j) == obj:
  884. return j
  885. else:
  886. if eqfn(lst.ll_getitem_fast(j), obj):
  887. return j
  888. j += 1
  889. raise ValueError # can't say 'list.index(x): x not in list'
  890. # not inlined by the JIT -- contains a loop
  891. def ll_listremove(lst, obj, eqfn):
  892. index = ll_listindex(lst, obj, eqfn) # raises ValueError if obj not in lst
  893. ll_delitem_nonneg(dum_nocheck, lst, index)
  894. def ll_inplace_mul(l, factor):
  895. length = l.ll_length()
  896. if factor < 0:
  897. factor = 0
  898. try:
  899. resultlen = ovfcheck(length * factor)
  900. except OverflowError:
  901. raise MemoryError
  902. res = l
  903. res._ll_resize(resultlen)
  904. #res._ll_resize_ge(resultlen)
  905. j = length
  906. while j < resultlen:
  907. i = 0
  908. while i < length:
  909. p = j + i
  910. res.ll_setitem_fast(p, l.ll_getitem_fast(i))
  911. i += 1
  912. j += length
  913. return res
  914. ll_inplace_mul.oopspec = 'list.inplace_mul(l, factor)'
  915. def ll_mul(RESLIST, l, factor):
  916. length = l.ll_length()
  917. if factor < 0:
  918. factor = 0
  919. try:
  920. resultlen = ovfcheck(length * factor)
  921. except OverflowError:
  922. raise MemoryError
  923. res = RESLIST.ll_newlist(resultlen)
  924. j = 0
  925. while j < resultlen:
  926. i = 0
  927. while i < length:
  928. p = j + i
  929. res.ll_setitem_fast(p, l.ll_getitem_fast(i))
  930. i += 1
  931. j += length
  932. return res
  933. # not inlined by the JIT -- contains a loop