list_ops.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. """List primitive ops."""
  2. from __future__ import annotations
  3. from mypyc.ir.ops import ERR_FALSE, ERR_MAGIC, ERR_NEVER
  4. from mypyc.ir.rtypes import (
  5. bit_rprimitive,
  6. c_int_rprimitive,
  7. c_pyssize_t_rprimitive,
  8. int64_rprimitive,
  9. int_rprimitive,
  10. list_rprimitive,
  11. object_rprimitive,
  12. short_int_rprimitive,
  13. )
  14. from mypyc.primitives.registry import (
  15. ERR_NEG_INT,
  16. binary_op,
  17. custom_op,
  18. function_op,
  19. load_address_op,
  20. method_op,
  21. )
  22. # Get the 'builtins.list' type object.
  23. load_address_op(name="builtins.list", type=object_rprimitive, src="PyList_Type")
  24. # list(obj)
  25. to_list = function_op(
  26. name="builtins.list",
  27. arg_types=[object_rprimitive],
  28. return_type=list_rprimitive,
  29. c_function_name="PySequence_List",
  30. error_kind=ERR_MAGIC,
  31. )
  32. # Construct an empty list via list().
  33. function_op(
  34. name="builtins.list",
  35. arg_types=[],
  36. return_type=list_rprimitive,
  37. c_function_name="PyList_New",
  38. error_kind=ERR_MAGIC,
  39. extra_int_constants=[(0, int_rprimitive)],
  40. )
  41. new_list_op = custom_op(
  42. arg_types=[c_pyssize_t_rprimitive],
  43. return_type=list_rprimitive,
  44. c_function_name="PyList_New",
  45. error_kind=ERR_MAGIC,
  46. )
  47. list_build_op = custom_op(
  48. arg_types=[c_pyssize_t_rprimitive],
  49. return_type=list_rprimitive,
  50. c_function_name="CPyList_Build",
  51. error_kind=ERR_MAGIC,
  52. var_arg_type=object_rprimitive,
  53. steals=True,
  54. )
  55. # list[index] (for an integer index)
  56. list_get_item_op = method_op(
  57. name="__getitem__",
  58. arg_types=[list_rprimitive, int_rprimitive],
  59. return_type=object_rprimitive,
  60. c_function_name="CPyList_GetItem",
  61. error_kind=ERR_MAGIC,
  62. )
  63. # list[index] version with no int tag check for when it is known to be short
  64. method_op(
  65. name="__getitem__",
  66. arg_types=[list_rprimitive, short_int_rprimitive],
  67. return_type=object_rprimitive,
  68. c_function_name="CPyList_GetItemShort",
  69. error_kind=ERR_MAGIC,
  70. priority=2,
  71. )
  72. # list[index] that produces a borrowed result
  73. method_op(
  74. name="__getitem__",
  75. arg_types=[list_rprimitive, int_rprimitive],
  76. return_type=object_rprimitive,
  77. c_function_name="CPyList_GetItemBorrow",
  78. error_kind=ERR_MAGIC,
  79. is_borrowed=True,
  80. priority=3,
  81. )
  82. # list[index] that produces a borrowed result and index is known to be short
  83. method_op(
  84. name="__getitem__",
  85. arg_types=[list_rprimitive, short_int_rprimitive],
  86. return_type=object_rprimitive,
  87. c_function_name="CPyList_GetItemShortBorrow",
  88. error_kind=ERR_MAGIC,
  89. is_borrowed=True,
  90. priority=4,
  91. )
  92. # Version with native int index
  93. method_op(
  94. name="__getitem__",
  95. arg_types=[list_rprimitive, int64_rprimitive],
  96. return_type=object_rprimitive,
  97. c_function_name="CPyList_GetItemInt64",
  98. error_kind=ERR_MAGIC,
  99. priority=5,
  100. )
  101. # Version with native int index
  102. method_op(
  103. name="__getitem__",
  104. arg_types=[list_rprimitive, int64_rprimitive],
  105. return_type=object_rprimitive,
  106. c_function_name="CPyList_GetItemInt64Borrow",
  107. is_borrowed=True,
  108. error_kind=ERR_MAGIC,
  109. priority=6,
  110. )
  111. # This is unsafe because it assumes that the index is a non-negative short integer
  112. # that is in-bounds for the list.
  113. list_get_item_unsafe_op = custom_op(
  114. arg_types=[list_rprimitive, short_int_rprimitive],
  115. return_type=object_rprimitive,
  116. c_function_name="CPyList_GetItemUnsafe",
  117. error_kind=ERR_NEVER,
  118. )
  119. # list[index] = obj
  120. list_set_item_op = method_op(
  121. name="__setitem__",
  122. arg_types=[list_rprimitive, int_rprimitive, object_rprimitive],
  123. return_type=bit_rprimitive,
  124. c_function_name="CPyList_SetItem",
  125. error_kind=ERR_FALSE,
  126. steals=[False, False, True],
  127. )
  128. # list[index_i64] = obj
  129. method_op(
  130. name="__setitem__",
  131. arg_types=[list_rprimitive, int64_rprimitive, object_rprimitive],
  132. return_type=bit_rprimitive,
  133. c_function_name="CPyList_SetItemInt64",
  134. error_kind=ERR_FALSE,
  135. steals=[False, False, True],
  136. priority=2,
  137. )
  138. # PyList_SET_ITEM does no error checking,
  139. # and should only be used to fill in brand new lists.
  140. new_list_set_item_op = custom_op(
  141. arg_types=[list_rprimitive, int_rprimitive, object_rprimitive],
  142. return_type=bit_rprimitive,
  143. c_function_name="CPyList_SetItemUnsafe",
  144. error_kind=ERR_FALSE,
  145. steals=[False, False, True],
  146. )
  147. # list.append(obj)
  148. list_append_op = method_op(
  149. name="append",
  150. arg_types=[list_rprimitive, object_rprimitive],
  151. return_type=c_int_rprimitive,
  152. c_function_name="PyList_Append",
  153. error_kind=ERR_NEG_INT,
  154. )
  155. # list.extend(obj)
  156. list_extend_op = method_op(
  157. name="extend",
  158. arg_types=[list_rprimitive, object_rprimitive],
  159. return_type=object_rprimitive,
  160. c_function_name="CPyList_Extend",
  161. error_kind=ERR_MAGIC,
  162. )
  163. # list.pop()
  164. list_pop_last = method_op(
  165. name="pop",
  166. arg_types=[list_rprimitive],
  167. return_type=object_rprimitive,
  168. c_function_name="CPyList_PopLast",
  169. error_kind=ERR_MAGIC,
  170. )
  171. # list.pop(index)
  172. list_pop = method_op(
  173. name="pop",
  174. arg_types=[list_rprimitive, int_rprimitive],
  175. return_type=object_rprimitive,
  176. c_function_name="CPyList_Pop",
  177. error_kind=ERR_MAGIC,
  178. )
  179. # list.count(obj)
  180. method_op(
  181. name="count",
  182. arg_types=[list_rprimitive, object_rprimitive],
  183. return_type=short_int_rprimitive,
  184. c_function_name="CPyList_Count",
  185. error_kind=ERR_MAGIC,
  186. )
  187. # list.insert(index, obj)
  188. method_op(
  189. name="insert",
  190. arg_types=[list_rprimitive, int_rprimitive, object_rprimitive],
  191. return_type=c_int_rprimitive,
  192. c_function_name="CPyList_Insert",
  193. error_kind=ERR_NEG_INT,
  194. )
  195. # list.sort()
  196. method_op(
  197. name="sort",
  198. arg_types=[list_rprimitive],
  199. return_type=c_int_rprimitive,
  200. c_function_name="PyList_Sort",
  201. error_kind=ERR_NEG_INT,
  202. )
  203. # list.reverse()
  204. method_op(
  205. name="reverse",
  206. arg_types=[list_rprimitive],
  207. return_type=c_int_rprimitive,
  208. c_function_name="PyList_Reverse",
  209. error_kind=ERR_NEG_INT,
  210. )
  211. # list.remove(obj)
  212. method_op(
  213. name="remove",
  214. arg_types=[list_rprimitive, object_rprimitive],
  215. return_type=c_int_rprimitive,
  216. c_function_name="CPyList_Remove",
  217. error_kind=ERR_NEG_INT,
  218. )
  219. # list.index(obj)
  220. method_op(
  221. name="index",
  222. arg_types=[list_rprimitive, object_rprimitive],
  223. return_type=int_rprimitive,
  224. c_function_name="CPyList_Index",
  225. error_kind=ERR_MAGIC,
  226. )
  227. # list * int
  228. binary_op(
  229. name="*",
  230. arg_types=[list_rprimitive, int_rprimitive],
  231. return_type=list_rprimitive,
  232. c_function_name="CPySequence_Multiply",
  233. error_kind=ERR_MAGIC,
  234. )
  235. # int * list
  236. binary_op(
  237. name="*",
  238. arg_types=[int_rprimitive, list_rprimitive],
  239. return_type=list_rprimitive,
  240. c_function_name="CPySequence_RMultiply",
  241. error_kind=ERR_MAGIC,
  242. )
  243. # list[begin:end]
  244. list_slice_op = custom_op(
  245. arg_types=[list_rprimitive, int_rprimitive, int_rprimitive],
  246. return_type=object_rprimitive,
  247. c_function_name="CPyList_GetSlice",
  248. error_kind=ERR_MAGIC,
  249. )
  250. supports_sequence_protocol = custom_op(
  251. arg_types=[object_rprimitive],
  252. return_type=c_int_rprimitive,
  253. c_function_name="CPySequence_Check",
  254. error_kind=ERR_NEVER,
  255. )
  256. sequence_get_item = custom_op(
  257. arg_types=[object_rprimitive, c_pyssize_t_rprimitive],
  258. return_type=object_rprimitive,
  259. c_function_name="PySequence_GetItem",
  260. error_kind=ERR_NEVER,
  261. )
  262. sequence_get_slice = custom_op(
  263. arg_types=[object_rprimitive, c_pyssize_t_rprimitive, c_pyssize_t_rprimitive],
  264. return_type=object_rprimitive,
  265. c_function_name="PySequence_GetSlice",
  266. error_kind=ERR_MAGIC,
  267. )