this repo has no description
at trunk 297 lines 9.3 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2// listobject.c implementation 3 4#include "cpython-func.h" 5 6#include "api-handle.h" 7#include "handles.h" 8#include "list-builtins.h" 9#include "objects.h" 10#include "runtime.h" 11 12namespace py { 13 14PY_EXPORT PyTypeObject* PyListIter_Type_Ptr() { 15 Runtime* runtime = Thread::current()->runtime(); 16 return reinterpret_cast<PyTypeObject*>(ApiHandle::borrowedReference( 17 runtime, runtime->typeAt(LayoutId::kListIterator))); 18} 19 20PY_EXPORT PyObject* PyList_New(Py_ssize_t size) { 21 Thread* thread = Thread::current(); 22 if (size < 0) { 23 thread->raiseBadInternalCall(); 24 return nullptr; 25 } 26 27 Runtime* runtime = thread->runtime(); 28 if (size == 0) { 29 return ApiHandle::newReferenceWithManaged(runtime, runtime->newList()); 30 } 31 32 HandleScope scope(thread); 33 List list(&scope, runtime->newList()); 34 list.setItems(runtime->newMutableTuple(size)); 35 list.setNumItems(size); 36 return ApiHandle::newReferenceWithManaged(runtime, *list); 37} 38 39PY_EXPORT PyTypeObject* PyList_Type_Ptr() { 40 Runtime* runtime = Thread::current()->runtime(); 41 return reinterpret_cast<PyTypeObject*>( 42 ApiHandle::borrowedReference(runtime, runtime->typeAt(LayoutId::kList))); 43} 44 45PY_EXPORT int PyList_CheckExact_Func(PyObject* obj) { 46 return ApiHandle::asObject(ApiHandle::fromPyObject(obj)).isList(); 47} 48 49PY_EXPORT int PyList_Check_Func(PyObject* obj) { 50 return Thread::current()->runtime()->isInstanceOfList( 51 ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 52} 53 54PY_EXPORT PyObject* PyList_AsTuple(PyObject* pylist) { 55 Thread* thread = Thread::current(); 56 Runtime* runtime = thread->runtime(); 57 HandleScope scope(thread); 58 if (pylist == nullptr) { 59 thread->raiseBadInternalCall(); 60 return nullptr; 61 } 62 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist))); 63 if (!runtime->isInstanceOfList(*list_obj)) { 64 thread->raiseBadInternalCall(); 65 return nullptr; 66 } 67 List list(&scope, *list_obj); 68 word length = list.numItems(); 69 if (length == 0) { 70 return ApiHandle::newReferenceWithManaged(runtime, runtime->emptyTuple()); 71 } 72 MutableTuple result(&scope, runtime->newMutableTuple(length)); 73 result.replaceFromWith(0, Tuple::cast(list.items()), length); 74 return ApiHandle::newReferenceWithManaged(runtime, result.becomeImmutable()); 75} 76 77PY_EXPORT PyObject* PyList_GetItem(PyObject* pylist, Py_ssize_t i) { 78 Thread* thread = Thread::current(); 79 Runtime* runtime = thread->runtime(); 80 HandleScope scope(thread); 81 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist))); 82 if (!runtime->isInstanceOfList(*list_obj)) { 83 thread->raiseBadInternalCall(); 84 return nullptr; 85 } 86 List list(&scope, *list_obj); 87 if (i >= list.numItems()) { 88 thread->raiseWithFmt(LayoutId::kIndexError, 89 "index out of bounds in PyList_GetItem"); 90 return nullptr; 91 } 92 return ApiHandle::borrowedReference(runtime, list.at(i)); 93} 94 95PY_EXPORT int PyList_Reverse(PyObject* pylist) { 96 Thread* thread = Thread::current(); 97 if (pylist == nullptr) { 98 thread->raiseBadInternalCall(); 99 return -1; 100 } 101 Runtime* runtime = thread->runtime(); 102 HandleScope scope(thread); 103 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist))); 104 if (!runtime->isInstanceOfList(*list_obj)) { 105 thread->raiseBadInternalCall(); 106 return -1; 107 } 108 List list(&scope, *list_obj); 109 listReverse(thread, list); 110 return 0; 111} 112 113PY_EXPORT int PyList_SET_ITEM_Func(PyObject* pylist, Py_ssize_t i, 114 PyObject* item) { 115 Thread* thread = Thread::current(); 116 Runtime* runtime = thread->runtime(); 117 HandleScope scope(thread); 118 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist))); 119 DCHECK(runtime->isInstanceOfList(*list_obj), "pylist must be a list"); 120 List list(&scope, *list_obj); 121 DCHECK_INDEX(i, list.numItems()); 122 list.atPut(i, item == nullptr ? NoneType::object() 123 : ApiHandle::stealReference(item)); 124 return 0; 125} 126 127PY_EXPORT int PyList_SetItem(PyObject* pylist, Py_ssize_t i, PyObject* item) { 128 Thread* thread = Thread::current(); 129 Runtime* runtime = thread->runtime(); 130 HandleScope scope(thread); 131 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist))); 132 Object newitem(&scope, item == nullptr ? NoneType::object() 133 : ApiHandle::stealReference(item)); 134 if (!runtime->isInstanceOfList(*list_obj)) { 135 thread->raiseBadInternalCall(); 136 return -1; 137 } 138 List list(&scope, *list_obj); 139 if (i >= list.numItems()) { 140 thread->raiseWithFmt(LayoutId::kIndexError, 141 "index out of bounds in PyList_SetItem"); 142 return -1; 143 } 144 list.atPut(i, *newitem); 145 return 0; 146} 147 148PY_EXPORT int PyList_Append(PyObject* op, PyObject* newitem) { 149 Thread* thread = Thread::current(); 150 Runtime* runtime = thread->runtime(); 151 HandleScope scope(thread); 152 153 if (newitem == nullptr) { 154 thread->raiseBadInternalCall(); 155 return -1; 156 } 157 Object value(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(newitem))); 158 159 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(op))); 160 if (!runtime->isInstanceOfList(*list_obj)) { 161 thread->raiseBadInternalCall(); 162 return -1; 163 } 164 List list(&scope, *list_obj); 165 166 runtime->listAdd(thread, list, value); 167 return 0; 168} 169 170PY_EXPORT PyObject* PyList_GetSlice(PyObject* pylist, Py_ssize_t low, 171 Py_ssize_t high) { 172 Thread* thread = Thread::current(); 173 Runtime* runtime = thread->runtime(); 174 HandleScope scope(thread); 175 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist))); 176 if (!runtime->isInstanceOfList(*list_obj)) { 177 thread->raiseBadInternalCall(); 178 return nullptr; 179 } 180 List list(&scope, *list_obj); 181 word length = list.numItems(); 182 if (low < 0) { 183 low = 0; 184 } else if (low > length) { 185 low = length; 186 } 187 if (high < low) { 188 high = low; 189 } else if (high > length) { 190 high = length; 191 } 192 return ApiHandle::newReferenceWithManaged( 193 runtime, listSlice(thread, list, low, high, 1)); 194} 195 196PY_EXPORT int PyList_Insert(PyObject* pylist, Py_ssize_t where, 197 PyObject* item) { 198 Thread* thread = Thread::current(); 199 Runtime* runtime = thread->runtime(); 200 HandleScope scope(thread); 201 if (item == nullptr) { 202 thread->raiseBadInternalCall(); 203 return -1; 204 } 205 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist))); 206 if (!runtime->isInstanceOfList(*list_obj)) { 207 thread->raiseBadInternalCall(); 208 return -1; 209 } 210 List list(&scope, *list_obj); 211 if (list.numItems() == kMaxWord) { 212 thread->raiseWithFmt(LayoutId::kSystemError, 213 "cannot add more objects to list"); 214 return -1; 215 } 216 Object item_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(item))); 217 listInsert(thread, list, item_obj, where); 218 return 0; 219} 220 221PY_EXPORT int PyList_SetSlice(PyObject* list, Py_ssize_t low, Py_ssize_t high, 222 PyObject* items) { 223 Thread* thread = Thread::current(); 224 Runtime* runtime = thread->runtime(); 225 HandleScope scope(thread); 226 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(list))); 227 if (!runtime->isInstanceOfList(*list_obj)) { 228 thread->raiseBadInternalCall(); 229 return -1; 230 } 231 232 List self(&scope, *list_obj); 233 word length = self.numItems(); 234 if (low < 0) { 235 low = 0; 236 } else if (low > length) { 237 low = length; 238 } 239 if (high < low) { 240 high = low; 241 } else if (high > length) { 242 high = length; 243 } 244 245 Object start(&scope, SmallInt::fromWord(low)); 246 Object stop(&scope, SmallInt::fromWord(high)); 247 Object step(&scope, NoneType::object()); 248 Slice slice(&scope, runtime->newSlice(start, stop, step)); 249 Object result(&scope, NoneType::object()); 250 if (items == nullptr) { 251 // Equivalent to deleting slice 252 result = thread->invokeMethodStatic2(LayoutId::kList, ID(__delitem__), 253 list_obj, slice); 254 } else { 255 Object items_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(items))); 256 result = thread->invokeMethodStatic3(LayoutId::kList, ID(__setitem__), 257 list_obj, slice, items_obj); 258 } 259 return result.isError() ? -1 : 0; 260} 261 262PY_EXPORT Py_ssize_t PyList_Size(PyObject* p) { 263 Thread* thread = Thread::current(); 264 Runtime* runtime = thread->runtime(); 265 HandleScope scope(thread); 266 267 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(p))); 268 if (!runtime->isInstanceOfList(*list_obj)) { 269 thread->raiseBadInternalCall(); 270 return -1; 271 } 272 273 List list(&scope, *list_obj); 274 return list.numItems(); 275} 276 277PY_EXPORT int PyList_Sort(PyObject* pylist) { 278 Thread* thread = Thread::current(); 279 if (pylist == nullptr) { 280 thread->raiseBadInternalCall(); 281 return -1; 282 } 283 HandleScope scope(thread); 284 Object list_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pylist))); 285 Runtime* runtime = thread->runtime(); 286 if (!runtime->isInstanceOfList(*list_obj)) { 287 thread->raiseBadInternalCall(); 288 return -1; 289 } 290 List list(&scope, *list_obj); 291 if (listSort(thread, list).isError()) { 292 return -1; 293 } 294 return 0; 295} 296 297} // namespace py