Commit 2928b4a5 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Make list more subclassing-friendly

parent daab2d1d
...@@ -28,7 +28,7 @@ Box* listIterIter(Box* s) { ...@@ -28,7 +28,7 @@ Box* listIterIter(Box* s) {
} }
Box* listIter(Box* s) { Box* listIter(Box* s) {
assert(s->cls == list_cls); assert(isSubclass(s->cls, list_cls));
BoxedList* self = static_cast<BoxedList*>(s); BoxedList* self = static_cast<BoxedList*>(s);
return new BoxedListIterator(self, 0); return new BoxedListIterator(self, 0);
} }
...@@ -62,7 +62,7 @@ Box* listiterNext(Box* s) { ...@@ -62,7 +62,7 @@ Box* listiterNext(Box* s) {
Box* listReversed(Box* s) { Box* listReversed(Box* s) {
assert(s->cls == list_cls); assert(isSubclass(s->cls, list_cls));
BoxedList* self = static_cast<BoxedList*>(s); BoxedList* self = static_cast<BoxedList*>(s);
return new (list_reverse_iterator_cls) BoxedListIterator(self, self->size - 1); return new (list_reverse_iterator_cls) BoxedListIterator(self, self->size - 1);
} }
...@@ -132,7 +132,7 @@ void BoxedList::ensure(int space) { ...@@ -132,7 +132,7 @@ void BoxedList::ensure(int space) {
extern "C" void listAppendInternal(Box* s, Box* v) { extern "C" void listAppendInternal(Box* s, Box* v) {
// Lock must be held! // Lock must be held!
assert(s->cls == list_cls); assert(isSubclass(s->cls, list_cls));
BoxedList* self = static_cast<BoxedList*>(s); BoxedList* self = static_cast<BoxedList*>(s);
assert(self->size <= self->capacity); assert(self->size <= self->capacity);
...@@ -147,7 +147,7 @@ extern "C" void listAppendInternal(Box* s, Box* v) { ...@@ -147,7 +147,7 @@ extern "C" void listAppendInternal(Box* s, Box* v) {
extern "C" void listAppendArrayInternal(Box* s, Box** v, int nelts) { extern "C" void listAppendArrayInternal(Box* s, Box** v, int nelts) {
// Lock must be held! // Lock must be held!
assert(s->cls == list_cls); assert(isSubclass(s->cls, list_cls));
BoxedList* self = static_cast<BoxedList*>(s); BoxedList* self = static_cast<BoxedList*>(s);
assert(self->size <= self->capacity); assert(self->size <= self->capacity);
...@@ -161,7 +161,7 @@ extern "C" void listAppendArrayInternal(Box* s, Box** v, int nelts) { ...@@ -161,7 +161,7 @@ extern "C" void listAppendArrayInternal(Box* s, Box** v, int nelts) {
// TODO the inliner doesn't want to inline these; is there any point to having them in the inline section? // TODO the inliner doesn't want to inline these; is there any point to having them in the inline section?
extern "C" Box* listAppend(Box* s, Box* v) { extern "C" Box* listAppend(Box* s, Box* v) {
assert(s->cls == list_cls); assert(isSubclass(s->cls, list_cls));
BoxedList* self = static_cast<BoxedList*>(s); BoxedList* self = static_cast<BoxedList*>(s);
LOCK_REGION(self->lock.asWrite()); LOCK_REGION(self->lock.asWrite());
......
...@@ -116,12 +116,12 @@ extern "C" Box* listPop(BoxedList* self, Box* idx) { ...@@ -116,12 +116,12 @@ extern "C" Box* listPop(BoxedList* self, Box* idx) {
} }
extern "C" Py_ssize_t PyList_Size(PyObject* self) noexcept { extern "C" Py_ssize_t PyList_Size(PyObject* self) noexcept {
RELEASE_ASSERT(self->cls == list_cls, ""); RELEASE_ASSERT(isSubclass(self->cls, list_cls), "");
return static_cast<BoxedList*>(self)->size; return static_cast<BoxedList*>(self)->size;
} }
extern "C" Box* listLen(BoxedList* self) { extern "C" Box* listLen(BoxedList* self) {
assert(self->cls == list_cls); assert(isSubclass(self->cls, list_cls));
return boxInt(self->size); return boxInt(self->size);
} }
...@@ -148,7 +148,7 @@ Box* _listSlice(BoxedList* self, i64 start, i64 stop, i64 step, i64 length) { ...@@ -148,7 +148,7 @@ Box* _listSlice(BoxedList* self, i64 start, i64 stop, i64 step, i64 length) {
extern "C" Box* listGetitemUnboxed(BoxedList* self, int64_t n) { extern "C" Box* listGetitemUnboxed(BoxedList* self, int64_t n) {
LOCK_REGION(self->lock.asRead()); LOCK_REGION(self->lock.asRead());
assert(self->cls == list_cls); assert(isSubclass(self->cls, list_cls));
if (n < 0) if (n < 0)
n = self->size + n; n = self->size + n;
...@@ -177,7 +177,7 @@ extern "C" PyObject* PyList_GetItem(PyObject* op, Py_ssize_t i) noexcept { ...@@ -177,7 +177,7 @@ extern "C" PyObject* PyList_GetItem(PyObject* op, Py_ssize_t i) noexcept {
extern "C" Box* listGetitemSlice(BoxedList* self, BoxedSlice* slice) { extern "C" Box* listGetitemSlice(BoxedList* self, BoxedSlice* slice) {
LOCK_REGION(self->lock.asRead()); LOCK_REGION(self->lock.asRead());
assert(self->cls == list_cls); assert(isSubclass(self->cls, list_cls));
assert(slice->cls == slice_cls); assert(slice->cls == slice_cls);
i64 start, stop, step, length; i64 start, stop, step, length;
parseSlice(slice, self->size, &start, &stop, &step, &length); parseSlice(slice, self->size, &start, &stop, &step, &length);
...@@ -185,7 +185,7 @@ extern "C" Box* listGetitemSlice(BoxedList* self, BoxedSlice* slice) { ...@@ -185,7 +185,7 @@ extern "C" Box* listGetitemSlice(BoxedList* self, BoxedSlice* slice) {
} }
extern "C" Box* listGetitem(BoxedList* self, Box* slice) { extern "C" Box* listGetitem(BoxedList* self, Box* slice) {
assert(self->cls == list_cls); assert(isSubclass(self->cls, list_cls));
if (isSubclass(slice->cls, int_cls)) { if (isSubclass(slice->cls, int_cls)) {
return listGetitemInt(self, static_cast<BoxedInt*>(slice)); return listGetitemInt(self, static_cast<BoxedInt*>(slice));
} else if (slice->cls == slice_cls) { } else if (slice->cls == slice_cls) {
...@@ -210,7 +210,7 @@ extern "C" Box* listSetitemInt(BoxedList* self, BoxedInt* slice, Box* v) { ...@@ -210,7 +210,7 @@ extern "C" Box* listSetitemInt(BoxedList* self, BoxedInt* slice, Box* v) {
// I think r lock is ok here, since we don't change the list structure: // I think r lock is ok here, since we don't change the list structure:
LOCK_REGION(self->lock.asRead()); LOCK_REGION(self->lock.asRead());
assert(self->cls == list_cls); assert(isSubclass(self->cls, list_cls));
assert(isSubclass(slice->cls, int_cls)); assert(isSubclass(slice->cls, int_cls));
int64_t n = slice->n; int64_t n = slice->n;
...@@ -220,7 +220,7 @@ extern "C" Box* listSetitemInt(BoxedList* self, BoxedInt* slice, Box* v) { ...@@ -220,7 +220,7 @@ extern "C" Box* listSetitemInt(BoxedList* self, BoxedInt* slice, Box* v) {
} }
extern "C" int PyList_SetItem(PyObject* op, Py_ssize_t i, PyObject* newitem) noexcept { extern "C" int PyList_SetItem(PyObject* op, Py_ssize_t i, PyObject* newitem) noexcept {
assert(op->cls == list_cls); assert(isSubclass(op->cls, list_cls));
try { try {
_listSetitem(static_cast<BoxedList*>(op), i, newitem); _listSetitem(static_cast<BoxedList*>(op), i, newitem);
} catch (ExcInfo e) { } catch (ExcInfo e) {
...@@ -243,7 +243,7 @@ static void sliceIndex(Box* b, int64_t* out) { ...@@ -243,7 +243,7 @@ static void sliceIndex(Box* b, int64_t* out) {
extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) { extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) {
LOCK_REGION(self->lock.asWrite()); LOCK_REGION(self->lock.asWrite());
assert(self->cls == list_cls); assert(isSubclass(self->cls, list_cls));
assert(slice->cls == slice_cls); assert(slice->cls == slice_cls);
i64 start = 0, stop = self->size, step = 1; i64 start = 0, stop = self->size, step = 1;
...@@ -273,7 +273,7 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) { ...@@ -273,7 +273,7 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) {
assert(0 <= start && start <= stop && stop <= self->size); assert(0 <= start && start <= stop && stop <= self->size);
RELEASE_ASSERT(v->cls == list_cls, "unsupported %s", getTypeName(v)); RELEASE_ASSERT(isSubclass(v->cls, list_cls), "unsupported %s", getTypeName(v));
BoxedList* lv = static_cast<BoxedList*>(v); BoxedList* lv = static_cast<BoxedList*>(v);
RELEASE_ASSERT(self->elts != lv->elts, "Slice self-assignment currently unsupported"); RELEASE_ASSERT(self->elts != lv->elts, "Slice self-assignment currently unsupported");
...@@ -294,7 +294,7 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) { ...@@ -294,7 +294,7 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) {
} }
extern "C" Box* listSetitem(BoxedList* self, Box* slice, Box* v) { extern "C" Box* listSetitem(BoxedList* self, Box* slice, Box* v) {
assert(self->cls == list_cls); assert(isSubclass(self->cls, list_cls));
if (isSubclass(slice->cls, int_cls)) { if (isSubclass(slice->cls, int_cls)) {
return listSetitemInt(self, static_cast<BoxedInt*>(slice), v); return listSetitemInt(self, static_cast<BoxedInt*>(slice), v);
} else if (slice->cls == slice_cls) { } else if (slice->cls == slice_cls) {
...@@ -455,7 +455,7 @@ Box* listAdd(BoxedList* self, Box* _rhs) { ...@@ -455,7 +455,7 @@ Box* listAdd(BoxedList* self, Box* _rhs) {
Box* listReverse(BoxedList* self) { Box* listReverse(BoxedList* self) {
LOCK_REGION(self->lock.asWrite()); LOCK_REGION(self->lock.asWrite());
assert(self->cls == list_cls); assert(isSubclass(self->cls, list_cls));
for (int i = 0, j = self->size - 1; i < j; i++, j--) { for (int i = 0, j = self->size - 1; i < j; i++, j--) {
Box* e = self->elts->elts[i]; Box* e = self->elts->elts[i];
self->elts->elts[i] = self->elts->elts[j]; self->elts->elts[i] = self->elts->elts[j];
...@@ -482,7 +482,7 @@ extern "C" int PyList_Reverse(PyObject* v) noexcept { ...@@ -482,7 +482,7 @@ extern "C" int PyList_Reverse(PyObject* v) noexcept {
void listSort(BoxedList* self, Box* cmp, Box* key, Box* reverse) { void listSort(BoxedList* self, Box* cmp, Box* key, Box* reverse) {
LOCK_REGION(self->lock.asWrite()); LOCK_REGION(self->lock.asWrite());
assert(self->cls == list_cls); assert(isSubclass(self->cls, list_cls));
RELEASE_ASSERT(cmp == None, "The 'cmp' keyword is currently not supported"); RELEASE_ASSERT(cmp == None, "The 'cmp' keyword is currently not supported");
...@@ -609,7 +609,7 @@ Box* listIndex(BoxedList* self, Box* elt) { ...@@ -609,7 +609,7 @@ Box* listIndex(BoxedList* self, Box* elt) {
Box* listRemove(BoxedList* self, Box* elt) { Box* listRemove(BoxedList* self, Box* elt) {
LOCK_REGION(self->lock.asWrite()); LOCK_REGION(self->lock.asWrite());
assert(self->cls == list_cls); assert(isSubclass(self->cls, list_cls));
for (int i = 0; i < self->size; i++) { for (int i = 0; i < self->size; i++) {
Box* e = self->elts->elts[i]; Box* e = self->elts->elts[i];
...@@ -635,17 +635,22 @@ extern "C" void listIteratorGCHandler(GCVisitor* v, Box* b) { ...@@ -635,17 +635,22 @@ extern "C" void listIteratorGCHandler(GCVisitor* v, Box* b) {
v->visit(it->l); v->visit(it->l);
} }
extern "C" Box* listNew(Box* cls, Box* container) { Box* listNew(BoxedClass* cls, Box* container) {
assert(isSubclass(static_cast<BoxedClass*>(cls), list_cls)); assert(cls->cls == type_cls);
assert(isSubclass(cls, list_cls));
return new (cls) BoxedList();
}
if (container == None) Box* listInit(BoxedList* self, Box* container) {
return new BoxedList(); assert(isSubclass(self->cls, list_cls));
BoxedList* rtn = new BoxedList(); if (container != None) {
for (Box* e : container->pyElements()) { for (Box* e : container->pyElements()) {
listAppendInternal(rtn, e); listAppendInternal(self, e);
} }
return rtn; }
return None;
} }
extern "C" PyObject* PyList_New(Py_ssize_t size) noexcept { extern "C" PyObject* PyList_New(Py_ssize_t size) noexcept {
...@@ -743,7 +748,7 @@ Box* listNe(BoxedList* self, Box* rhs) { ...@@ -743,7 +748,7 @@ Box* listNe(BoxedList* self, Box* rhs) {
extern "C" PyObject* _PyList_Extend(PyListObject* self, PyObject* b) noexcept { extern "C" PyObject* _PyList_Extend(PyListObject* self, PyObject* b) noexcept {
BoxedList* l = (BoxedList*)self; BoxedList* l = (BoxedList*)self;
assert(l->cls == list_cls); assert(isSubclass(l->cls, list_cls));
try { try {
return listIAdd(l, b); return listIAdd(l, b);
...@@ -760,7 +765,7 @@ extern "C" int PyList_SetSlice(PyObject* a, Py_ssize_t ilow, Py_ssize_t ihigh, P ...@@ -760,7 +765,7 @@ extern "C" int PyList_SetSlice(PyObject* a, Py_ssize_t ilow, Py_ssize_t ihigh, P
} }
BoxedList* l = (BoxedList*)a; BoxedList* l = (BoxedList*)a;
ASSERT(l->cls == list_cls, "%s", l->cls->tp_name); ASSERT(isSubclass(l->cls, list_cls), "%s", l->cls->tp_name);
try { try {
if (v) if (v)
...@@ -831,6 +836,8 @@ void setupList() { ...@@ -831,6 +836,8 @@ void setupList() {
list_cls->giveAttr("__new__", list_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)listNew, UNKNOWN, 2, 1, false, false), { None })); new BoxedFunction(boxRTFunction((void*)listNew, UNKNOWN, 2, 1, false, false), { None }));
list_cls->giveAttr("__init__",
new BoxedFunction(boxRTFunction((void*)listInit, UNKNOWN, 2, 1, false, false), { None }));
list_cls->giveAttr("count", new BoxedFunction(boxRTFunction((void*)listCount, BOXED_INT, 2))); list_cls->giveAttr("count", new BoxedFunction(boxRTFunction((void*)listCount, BOXED_INT, 2)));
list_cls->giveAttr("index", new BoxedFunction(boxRTFunction((void*)listIndex, BOXED_INT, 2))); list_cls->giveAttr("index", new BoxedFunction(boxRTFunction((void*)listIndex, BOXED_INT, 2)));
......
class MyList(list):
pass
l = MyList(range(5))
print type(l)
l.foo = 1
print l.foo
print l
print len(MyList.__new__(MyList))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment