Commit a55fc0b2 authored by Marius Wachtler's avatar Marius Wachtler

Add missing tp_iter and tp_iternext functions

parent dd45bf69
...@@ -1125,13 +1125,7 @@ static PyObject* slot_tp_del(PyObject* self) noexcept { ...@@ -1125,13 +1125,7 @@ static PyObject* slot_tp_del(PyObject* self) noexcept {
PyObject* slot_sq_item(PyObject* self, Py_ssize_t i) noexcept { PyObject* slot_sq_item(PyObject* self, Py_ssize_t i) noexcept {
STAT_TIMER(t0, "us_timer_slot_sqitem", SLOT_AVOIDABILITY(self)); STAT_TIMER(t0, "us_timer_slot_sqitem", SLOT_AVOIDABILITY(self));
return getitemInternal<CAPI>(self, boxInt(i), NULL);
try {
return getitem(self, boxInt(i));
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
} }
/* Pyston change: static */ Py_ssize_t slot_sq_length(PyObject* self) noexcept { /* Pyston change: static */ Py_ssize_t slot_sq_length(PyObject* self) noexcept {
......
...@@ -1636,7 +1636,7 @@ void setupBuiltins() { ...@@ -1636,7 +1636,7 @@ void setupBuiltins() {
enumerate_cls->giveAttr("__hasnext__", enumerate_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)BoxedEnumerate::hasnext, BOXED_BOOL, 1))); new BoxedFunction(boxRTFunction((void*)BoxedEnumerate::hasnext, BOXED_BOOL, 1)));
enumerate_cls->freeze(); enumerate_cls->freeze();
enumerate_cls->tp_iter = BoxedEnumerate::iter; enumerate_cls->tp_iter = PyObject_SelfIter;
builtins_module->giveAttr("enumerate", enumerate_cls); builtins_module->giveAttr("enumerate", enumerate_cls);
......
...@@ -854,6 +854,7 @@ void setupDict() { ...@@ -854,6 +854,7 @@ void setupDict() {
"__iter__", new BoxedFunction(boxRTFunction((void*)dictIterIter, typeFromClass(dict_iterator_cls), 1))); "__iter__", new BoxedFunction(boxRTFunction((void*)dictIterIter, typeFromClass(dict_iterator_cls), 1)));
dict_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)dictIterNext, UNKNOWN, 1))); dict_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)dictIterNext, UNKNOWN, 1)));
dict_iterator_cls->freeze(); dict_iterator_cls->freeze();
dict_iterator_cls->tp_iter = PyObject_SelfIter;
dict_iterator_cls->tp_iternext = dictiter_next; dict_iterator_cls->tp_iternext = dictiter_next;
// Manually set some tp_* slots *after* calling freeze() -> fixup_slot_dispatchers(). // Manually set some tp_* slots *after* calling freeze() -> fixup_slot_dispatchers().
...@@ -869,6 +870,7 @@ void setupDict() { ...@@ -869,6 +870,7 @@ void setupDict() {
// subclass Python classes. // subclass Python classes.
dict_cls->tp_init = dict_init; dict_cls->tp_init = dict_init;
dict_cls->tp_repr = dict_repr; dict_cls->tp_repr = dict_repr;
dict_cls->tp_iter = dict_iter;
dict_cls->tp_as_mapping->mp_length = (lenfunc)dict_length; dict_cls->tp_as_mapping->mp_length = (lenfunc)dict_length;
dict_cls->tp_as_mapping->mp_subscript = (binaryfunc)dictGetitem<CAPI>; dict_cls->tp_as_mapping->mp_subscript = (binaryfunc)dictGetitem<CAPI>;
......
...@@ -43,6 +43,7 @@ public: ...@@ -43,6 +43,7 @@ public:
Box* dictGetitem(BoxedDict* self, Box* k); Box* dictGetitem(BoxedDict* self, Box* k);
Box* dict_iter(Box* s) noexcept;
Box* dictIterKeys(Box* self); Box* dictIterKeys(Box* self);
Box* dictIterValues(Box* self); Box* dictIterValues(Box* self);
Box* dictIterItems(Box* self); Box* dictIterItems(Box* self);
......
...@@ -23,12 +23,16 @@ BoxedDictIterator::BoxedDictIterator(BoxedDict* d, IteratorType type) ...@@ -23,12 +23,16 @@ BoxedDictIterator::BoxedDictIterator(BoxedDict* d, IteratorType type)
: d(d), it(d->d.begin()), itEnd(d->d.end()), type(type) { : d(d), it(d->d.begin()), itEnd(d->d.end()), type(type) {
} }
Box* dictIterKeys(Box* s) { Box* dict_iter(Box* s) noexcept {
assert(PyDict_Check(s)); assert(PyDict_Check(s));
BoxedDict* self = static_cast<BoxedDict*>(s); BoxedDict* self = static_cast<BoxedDict*>(s);
return new BoxedDictIterator(self, BoxedDictIterator::KeyIterator); return new BoxedDictIterator(self, BoxedDictIterator::KeyIterator);
} }
Box* dictIterKeys(Box* s) {
return dict_iter(s);
}
Box* dictIterValues(Box* s) { Box* dictIterValues(Box* s) {
assert(PyDict_Check(s)); assert(PyDict_Check(s));
BoxedDict* self = static_cast<BoxedDict*>(s); BoxedDict* self = static_cast<BoxedDict*>(s);
......
...@@ -244,5 +244,6 @@ void setupXrange() { ...@@ -244,5 +244,6 @@ void setupXrange() {
xrange_iterator_cls->freeze(); xrange_iterator_cls->freeze();
xrange_iterator_cls->tpp_hasnext = BoxedXrangeIterator::xrangeIteratorHasnextUnboxed; xrange_iterator_cls->tpp_hasnext = BoxedXrangeIterator::xrangeIteratorHasnextUnboxed;
xrange_iterator_cls->tp_iternext = BoxedXrangeIterator::xrangeIterator_next; xrange_iterator_cls->tp_iternext = BoxedXrangeIterator::xrangeIterator_next;
xrange_iterator_cls->tp_iter = PyObject_SelfIter;
} }
} }
...@@ -40,69 +40,82 @@ Box* seqiterIter(Box* s) { ...@@ -40,69 +40,82 @@ Box* seqiterIter(Box* s) {
return s; return s;
} }
bool seqiterHasnextUnboxed(Box* s) { static Box* seqiterHasnext_capi(Box* s) noexcept {
RELEASE_ASSERT(s->cls == seqiter_cls || s->cls == seqreviter_cls, ""); RELEASE_ASSERT(s->cls == seqiter_cls || s->cls == seqreviter_cls, "");
BoxedSeqIter* self = static_cast<BoxedSeqIter*>(s); BoxedSeqIter* self = static_cast<BoxedSeqIter*>(s);
if (!self->b) { if (!self->b) {
return false; return False;
} }
Box* next = getitemInternal<ExceptionStyle::CAPI>(self->b, boxInt(self->idx), NULL); Box* next = PySequence_GetItem(self->b, self->idx);
if (!next) { if (!next) {
if (PyErr_ExceptionMatches(IndexError) || PyErr_ExceptionMatches(StopIteration)) { if (PyErr_ExceptionMatches(IndexError) || PyErr_ExceptionMatches(StopIteration)) {
PyErr_Clear(); PyErr_Clear();
self->b = NULL; self->b = NULL;
return false; return False;
} else {
throwCAPIException();
} }
return NULL;
} }
self->idx++; self->idx++;
self->next = next; self->next = next;
return true; return True;
} }
Box* seqiterHasnext(Box* s) { Box* seqiterHasnext(Box* s) {
return boxBool(seqiterHasnextUnboxed(s)); Box* rtn = seqiterHasnext_capi(s);
if (!rtn)
throwCAPIException();
return rtn;
} }
Box* seqreviterHasnext(Box* s) { bool seqiterHasnextUnboxed(Box* s) {
return unboxBool(seqiterHasnext(s));
}
Box* seqreviterHasnext_capi(Box* s) noexcept {
RELEASE_ASSERT(s->cls == seqiter_cls || s->cls == seqreviter_cls, ""); RELEASE_ASSERT(s->cls == seqiter_cls || s->cls == seqreviter_cls, "");
BoxedSeqIter* self = static_cast<BoxedSeqIter*>(s); BoxedSeqIter* self = static_cast<BoxedSeqIter*>(s);
if (self->idx == -1 || !self->b) if (self->idx == -1 || !self->b)
return False; return False;
Box* next;
try { Box* next = PySequence_GetItem(self->b, self->idx);
next = getitem(self->b, boxInt(self->idx)); if (!next) {
} catch (ExcInfo e) { if (PyErr_ExceptionMatches(IndexError) || PyErr_ExceptionMatches(StopIteration)) {
if (e.matches(IndexError) || e.matches(StopIteration)) { PyErr_Clear();
self->b = NULL; self->b = NULL;
return False; return False;
} else }
throw e; return NULL;
} }
self->idx--; self->idx--;
self->next = next; self->next = next;
return True; return True;
} }
Box* seqiterNext(Box* s) { Box* seqreviterHasnext(Box* s) {
Box* rtn = seqreviterHasnext_capi(s);
if (!rtn)
throwCAPIException();
return rtn;
}
Box* seqiter_next(Box* s) noexcept {
RELEASE_ASSERT(s->cls == seqiter_cls || s->cls == seqreviter_cls, ""); RELEASE_ASSERT(s->cls == seqiter_cls || s->cls == seqreviter_cls, "");
BoxedSeqIter* self = static_cast<BoxedSeqIter*>(s); BoxedSeqIter* self = static_cast<BoxedSeqIter*>(s);
if (!self->next) { if (!self->next) {
Box* hasnext = NULL; Box* hasnext = NULL;
if (s->cls == seqiter_cls) if (s->cls == seqiter_cls)
hasnext = seqiterHasnext(s); hasnext = seqiterHasnext_capi(s);
else if (s->cls == seqreviter_cls) else if (s->cls == seqreviter_cls)
hasnext = seqreviterHasnext(s); hasnext = seqreviterHasnext_capi(s);
else else
RELEASE_ASSERT(0, ""); RELEASE_ASSERT(0, "");
if (hasnext == False) if (hasnext != True)
raiseExcHelper(StopIteration, (const char*)NULL); return NULL;
} }
RELEASE_ASSERT(self->next, ""); RELEASE_ASSERT(self->next, "");
...@@ -111,6 +124,13 @@ Box* seqiterNext(Box* s) { ...@@ -111,6 +124,13 @@ Box* seqiterNext(Box* s) {
return r; return r;
} }
Box* seqiterNext(Box* s) {
Box* rtn = seqiter_next(s);
if (!rtn)
raiseExcHelper(StopIteration, (const char*)NULL);
return rtn;
}
void BoxedSeqIter::gcHandler(GCVisitor* v, Box* b) { void BoxedSeqIter::gcHandler(GCVisitor* v, Box* b) {
assert(b->cls == seqiter_cls || b->cls == seqreviter_cls); assert(b->cls == seqiter_cls || b->cls == seqreviter_cls);
Box::gcHandler(v, b); Box::gcHandler(v, b);
...@@ -149,16 +169,24 @@ Box* iterwrapperHasnext(Box* s) { ...@@ -149,16 +169,24 @@ Box* iterwrapperHasnext(Box* s) {
return boxBool(iterwrapperHasnextUnboxed(s)); return boxBool(iterwrapperHasnextUnboxed(s));
} }
Box* iterwrapperNext(Box* s) { Box* iterwrapper_next(Box* s) noexcept {
RELEASE_ASSERT(s->cls == iterwrapper_cls, ""); RELEASE_ASSERT(s->cls == iterwrapper_cls, "");
BoxedIterWrapper* self = static_cast<BoxedIterWrapper*>(s); BoxedIterWrapper* self = static_cast<BoxedIterWrapper*>(s);
RELEASE_ASSERT(self->next, ""); if (!self->next)
return NULL;
Box* r = self->next; Box* r = self->next;
self->next = NULL; self->next = NULL;
return r; return r;
} }
Box* iterwrapperNext(Box* s) {
Box* rtn = iterwrapper_next(s);
if (!rtn)
raiseExcHelper(StopIteration, (const char*)NULL);
return rtn;
}
extern "C" PyObject* PySeqIter_New(PyObject* seq) noexcept { extern "C" PyObject* PySeqIter_New(PyObject* seq) noexcept {
try { try {
return new BoxedSeqIter(seq, 0); return new BoxedSeqIter(seq, 0);
...@@ -190,6 +218,8 @@ void setupIter() { ...@@ -190,6 +218,8 @@ void setupIter() {
seqiter_cls->freeze(); seqiter_cls->freeze();
seqiter_cls->tpp_hasnext = seqiterHasnextUnboxed; seqiter_cls->tpp_hasnext = seqiterHasnextUnboxed;
seqiter_cls->tp_iter = PyObject_SelfIter;
seqiter_cls->tp_iternext = seqiter_next;
seqreviter_cls = BoxedClass::create(type_cls, object_cls, &BoxedSeqIter::gcHandler, 0, 0, sizeof(BoxedSeqIter), seqreviter_cls = BoxedClass::create(type_cls, object_cls, &BoxedSeqIter::gcHandler, 0, 0, sizeof(BoxedSeqIter),
false, "reversed"); false, "reversed");
...@@ -199,6 +229,8 @@ void setupIter() { ...@@ -199,6 +229,8 @@ void setupIter() {
seqreviter_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)seqiterIter, UNKNOWN, 1))); seqreviter_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)seqiterIter, UNKNOWN, 1)));
seqreviter_cls->freeze(); seqreviter_cls->freeze();
seqreviter_cls->tp_iter = PyObject_SelfIter;
seqreviter_cls->tp_iternext = seqiter_next;
iterwrapper_cls = BoxedClass::create(type_cls, object_cls, &BoxedIterWrapper::gcHandler, 0, 0, iterwrapper_cls = BoxedClass::create(type_cls, object_cls, &BoxedIterWrapper::gcHandler, 0, 0,
sizeof(BoxedIterWrapper), false, "iterwrapper"); sizeof(BoxedIterWrapper), false, "iterwrapper");
...@@ -209,5 +241,6 @@ void setupIter() { ...@@ -209,5 +241,6 @@ void setupIter() {
iterwrapper_cls->freeze(); iterwrapper_cls->freeze();
iterwrapper_cls->tpp_hasnext = iterwrapperHasnextUnboxed; iterwrapper_cls->tpp_hasnext = iterwrapperHasnextUnboxed;
iterwrapper_cls->tp_iternext = iterwrapper_next;
} }
} }
...@@ -1383,6 +1383,7 @@ void setupList() { ...@@ -1383,6 +1383,7 @@ void setupList() {
list_iterator_cls->freeze(); list_iterator_cls->freeze();
list_iterator_cls->tpp_hasnext = listiterHasnextUnboxed; list_iterator_cls->tpp_hasnext = listiterHasnextUnboxed;
list_iterator_cls->tp_iternext = listiter_next; list_iterator_cls->tp_iternext = listiter_next;
list_iterator_cls->tp_iter = PyObject_SelfIter;
list_reverse_iterator_cls->giveAttr("__name__", boxString("listreverseiterator")); list_reverse_iterator_cls->giveAttr("__name__", boxString("listreverseiterator"));
...@@ -1395,6 +1396,7 @@ void setupList() { ...@@ -1395,6 +1396,7 @@ void setupList() {
list_reverse_iterator_cls->freeze(); list_reverse_iterator_cls->freeze();
list_reverse_iterator_cls->tp_iternext = listreviter_next; list_reverse_iterator_cls->tp_iternext = listreviter_next;
list_reverse_iterator_cls->tp_iter = PyObject_SelfIter;
} }
void teardownList() { void teardownList() {
......
...@@ -5229,8 +5229,7 @@ extern "C" Box* getPystonIter(Box* o) { ...@@ -5229,8 +5229,7 @@ extern "C" Box* getPystonIter(Box* o) {
} }
extern "C" Box* getiterHelper(Box* o) { extern "C" Box* getiterHelper(Box* o) {
static BoxedString* getitem_str = internStringImmortal("__getitem__"); if (PySequence_Check(o))
if (typeLookup(o->cls, getitem_str, NULL))
return new BoxedSeqIter(o, 0); return new BoxedSeqIter(o, 0);
raiseExcHelper(TypeError, "'%s' object is not iterable", getTypeName(o)); raiseExcHelper(TypeError, "'%s' object is not iterable", getTypeName(o));
} }
......
...@@ -699,6 +699,7 @@ void setupSet() { ...@@ -699,6 +699,7 @@ void setupSet() {
set_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)setiteratorNext, UNKNOWN, 1))); set_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)setiteratorNext, UNKNOWN, 1)));
set_iterator_cls->freeze(); set_iterator_cls->freeze();
set_iterator_cls->tp_iternext = setiter_next; set_iterator_cls->tp_iternext = setiter_next;
set_iterator_cls->tp_iter = PyObject_SelfIter;
set_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)setNew, UNKNOWN, 2, false, false), { NULL })); set_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)setNew, UNKNOWN, 2, false, false), { NULL }));
set_cls->giveAttr("__init__", new BoxedFunction(boxRTFunction((void*)setInit, UNKNOWN, 2, false, false), { NULL })); set_cls->giveAttr("__init__", new BoxedFunction(boxRTFunction((void*)setInit, UNKNOWN, 2, false, false), { NULL }));
......
...@@ -2834,6 +2834,7 @@ void setupStr() { ...@@ -2834,6 +2834,7 @@ void setupStr() {
str_iterator_cls->freeze(); str_iterator_cls->freeze();
str_iterator_cls->tpp_hasnext = (BoxedClass::pyston_inquiry)BoxedStringIterator::hasnextUnboxed; str_iterator_cls->tpp_hasnext = (BoxedClass::pyston_inquiry)BoxedStringIterator::hasnextUnboxed;
str_iterator_cls->tp_iternext = BoxedStringIterator::next_capi; str_iterator_cls->tp_iternext = BoxedStringIterator::next_capi;
str_iterator_cls->tp_iter = PyObject_SelfIter;
str_cls->tp_as_buffer = &string_as_buffer; str_cls->tp_as_buffer = &string_as_buffer;
str_cls->tp_print = string_print; str_cls->tp_print = string_print;
......
...@@ -712,6 +712,7 @@ void setupTuple() { ...@@ -712,6 +712,7 @@ void setupTuple() {
tuple_iterator_cls->freeze(); tuple_iterator_cls->freeze();
tuple_iterator_cls->tpp_hasnext = tupleiterHasnextUnboxed; tuple_iterator_cls->tpp_hasnext = tupleiterHasnextUnboxed;
tuple_iterator_cls->tp_iternext = tupleiter_next; tuple_iterator_cls->tp_iternext = tupleiter_next;
tuple_iterator_cls->tp_iter = PyObject_SelfIter;
} }
void teardownTuple() { void teardownTuple() {
......
...@@ -2208,6 +2208,7 @@ public: ...@@ -2208,6 +2208,7 @@ public:
static Box* hasnext(Box* _self); static Box* hasnext(Box* _self);
static Box* next(Box* _self); static Box* next(Box* _self);
static Box* next_capi(Box* _self) noexcept;
}; };
// A dictionary-like wrapper around the attributes array. // A dictionary-like wrapper around the attributes array.
...@@ -2523,7 +2524,7 @@ public: ...@@ -2523,7 +2524,7 @@ public:
return None; return None;
} }
static Box* iter(Box* _self) { static Box* iter(Box* _self) noexcept {
RELEASE_ASSERT(_self->cls == attrwrapper_cls, ""); RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self); AttrWrapper* self = static_cast<AttrWrapper*>(_self);
...@@ -2573,6 +2574,18 @@ Box* AttrWrapperIter::next(Box* _self) { ...@@ -2573,6 +2574,18 @@ Box* AttrWrapperIter::next(Box* _self) {
return r; return r;
} }
Box* AttrWrapperIter::next_capi(Box* _self) noexcept {
RELEASE_ASSERT(_self->cls == attrwrapperiter_cls, "");
AttrWrapperIter* self = static_cast<AttrWrapperIter*>(_self);
RELEASE_ASSERT(self->hcls->type == HiddenClass::NORMAL || self->hcls->type == HiddenClass::SINGLETON, "");
if (self->it == self->hcls->getStrAttrOffsets().end())
return NULL;
Box* r = self->it->first;
++self->it;
return r;
}
Box* Box::getAttrWrapper() { Box* Box::getAttrWrapper() {
assert(cls->instancesHaveHCAttrs()); assert(cls->instancesHaveHCAttrs());
HCAttrs* attrs = getHCAttrsPtr(); HCAttrs* attrs = getHCAttrsPtr();
...@@ -3854,11 +3867,14 @@ void setupRuntime() { ...@@ -3854,11 +3867,14 @@ void setupRuntime() {
attrwrapper_cls->giveAttr("update", attrwrapper_cls->giveAttr("update",
new BoxedFunction(boxRTFunction((void*)AttrWrapper::update, NONE, 1, true, true))); new BoxedFunction(boxRTFunction((void*)AttrWrapper::update, NONE, 1, true, true)));
attrwrapper_cls->freeze(); attrwrapper_cls->freeze();
attrwrapper_cls->tp_iter = AttrWrapper::iter;
attrwrapperiter_cls->giveAttr("__hasnext__", attrwrapperiter_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)AttrWrapperIter::hasnext, UNKNOWN, 1))); new BoxedFunction(boxRTFunction((void*)AttrWrapperIter::hasnext, UNKNOWN, 1)));
attrwrapperiter_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)AttrWrapperIter::next, UNKNOWN, 1))); attrwrapperiter_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)AttrWrapperIter::next, UNKNOWN, 1)));
attrwrapperiter_cls->freeze(); attrwrapperiter_cls->freeze();
attrwrapperiter_cls->tp_iter = PyObject_SelfIter;
attrwrapperiter_cls->tp_iternext = AttrWrapperIter::next_capi;
setupBuiltins(); setupBuiltins();
_PyExc_Init(); _PyExc_Init();
......
...@@ -16,6 +16,7 @@ c2.b = 5 ...@@ -16,6 +16,7 @@ c2.b = 5
def p(): def p():
print sorted(c1.__dict__.items()), sorted(c2.__dict__.items()) print sorted(c1.__dict__.items()), sorted(c2.__dict__.items())
print sorted(list(iter(c1.__dict__))), sorted(list(iter(c2.__dict__)))
p() p()
......
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