Commit dcae8bea authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #73 from kkszysiu/tuple_iter_implementation

Implementation of __iter__ for tuple, added tests
parents 5e418340 8399ad46
...@@ -352,7 +352,7 @@ BoxedModule* builtins_module; ...@@ -352,7 +352,7 @@ BoxedModule* builtins_module;
// TODO looks like CPython and pypy put this into an "exceptions" module: // TODO looks like CPython and pypy put this into an "exceptions" module:
BoxedClass* Exception, *AssertionError, *AttributeError, *TypeError, *NameError, *KeyError, *IndexError, *IOError, BoxedClass* Exception, *AssertionError, *AttributeError, *TypeError, *NameError, *KeyError, *IndexError, *IOError,
*OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError, *RuntimeError, *ImportError; *OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError, *RuntimeError, *ImportError, *StopIteration;
const ObjectFlavor exception_flavor(&boxGCHandler, NULL); const ObjectFlavor exception_flavor(&boxGCHandler, NULL);
Box* exceptionNew1(BoxedClass* cls) { Box* exceptionNew1(BoxedClass* cls) {
...@@ -440,6 +440,7 @@ void setupBuiltins() { ...@@ -440,6 +440,7 @@ void setupBuiltins() {
UnboundLocalError = makeBuiltinException(Exception, "UnboundLocalError"); UnboundLocalError = makeBuiltinException(Exception, "UnboundLocalError");
RuntimeError = makeBuiltinException(Exception, "RuntimeError"); RuntimeError = makeBuiltinException(Exception, "RuntimeError");
ImportError = makeBuiltinException(Exception, "ImportError"); ImportError = makeBuiltinException(Exception, "ImportError");
StopIteration = makeBuiltinException(Exception, "StopIteration");
repr_obj = new BoxedFunction(boxRTFunction((void*)repr, NULL, 1, false)); repr_obj = new BoxedFunction(boxRTFunction((void*)repr, NULL, 1, false));
builtins_module->giveAttr("repr", repr_obj); builtins_module->giveAttr("repr", repr_obj);
......
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
namespace pyston { namespace pyston {
extern BoxedClass* dict_iterator_cls; extern BoxedClass* dict_iterator_cls;
struct BoxedDictIterator : public Box { class BoxedDictIterator : public Box {
public:
enum IteratorType { KeyIterator, ValueIterator, ItemIterator }; enum IteratorType { KeyIterator, ValueIterator, ItemIterator };
BoxedDict* d; BoxedDict* d;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <cstring> #include <cstring>
#include "runtime/gc_runtime.h" #include "runtime/gc_runtime.h"
#include "runtime/objmodel.h"
#include "runtime/list.h" #include "runtime/list.h"
namespace pyston { namespace pyston {
...@@ -23,6 +24,11 @@ namespace pyston { ...@@ -23,6 +24,11 @@ namespace pyston {
BoxedListIterator::BoxedListIterator(BoxedList* l) : Box(&list_iterator_flavor, list_iterator_cls), l(l), pos(0) { BoxedListIterator::BoxedListIterator(BoxedList* l) : Box(&list_iterator_flavor, list_iterator_cls), l(l), pos(0) {
} }
Box* listIterIter(Box* s) {
return s;
}
Box* listIter(Box* s) { Box* listIter(Box* s) {
assert(s->cls == list_cls); assert(s->cls == list_cls);
BoxedList* self = static_cast<BoxedList*>(s); BoxedList* self = static_cast<BoxedList*>(s);
...@@ -47,7 +53,10 @@ Box* listiterNext(Box* s) { ...@@ -47,7 +53,10 @@ Box* listiterNext(Box* s) {
assert(s->cls == list_iterator_cls); assert(s->cls == list_iterator_cls);
BoxedListIterator* self = static_cast<BoxedListIterator*>(s); BoxedListIterator* self = static_cast<BoxedListIterator*>(s);
assert(self->pos >= 0 && self->pos < self->l->size); if(!(self->pos >= 0 && self->pos < self->l->size)) {
raiseExcHelper(StopIteration, "");
}
Box* rtn = self->l->elts->elts[self->pos]; Box* rtn = self->l->elts->elts[self->pos];
self->pos++; self->pos++;
return rtn; return rtn;
......
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cstring>
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h"
#include "runtime/tuple.h"
namespace pyston {
BoxedTupleIterator::BoxedTupleIterator(BoxedTuple* t) : Box(&tuple_iterator_flavor, tuple_iterator_cls), t(t), pos(0) {
}
Box* tupleIterIter(Box* s) {
return s;
}
Box* tupleIter(Box* s) {
assert(s->cls == tuple_cls);
BoxedTuple* self = static_cast<BoxedTuple*>(s);
return new BoxedTupleIterator(self);
}
Box* tupleiterHasnext(Box* s) {
return boxBool(tupleiterHasnextUnboxed(s));
}
i1 tupleiterHasnextUnboxed(Box* s) {
assert(s->cls == tuple_iterator_cls);
BoxedTupleIterator* self = static_cast<BoxedTupleIterator*>(s);
return self->pos < self->t->elts.size();
}
Box* tupleiterNext(Box* s) {
assert(s->cls == tuple_iterator_cls);
BoxedTupleIterator* self = static_cast<BoxedTupleIterator*>(s);
if (!(self->pos >= 0 && self->pos < self->t->elts.size())) {
raiseExcHelper(StopIteration, "");
}
Box* rtn = self->t->elts[self->pos];
self->pos++;
return rtn;
}
}
...@@ -432,6 +432,54 @@ extern "C" Box* listNew2(Box* cls, Box* container) { ...@@ -432,6 +432,54 @@ extern "C" Box* listNew2(Box* cls, Box* container) {
return rtn; return rtn;
} }
Box* _listCmp(BoxedList* lhs, BoxedList* rhs, AST_TYPE::AST_TYPE op_type) {
int lsz = lhs->size;
int rsz = rhs->size;
bool is_order
= (op_type == AST_TYPE::Lt || op_type == AST_TYPE::LtE || op_type == AST_TYPE::Gt || op_type == AST_TYPE::GtE);
int n = std::min(lsz, rsz);
for (int i = 0; i < n; i++) {
Box* is_eq = compareInternal(lhs->elts->elts[i], rhs->elts->elts[i], AST_TYPE::Eq, NULL);
bool bis_eq = nonzero(is_eq);
if (bis_eq)
continue;
if (op_type == AST_TYPE::Eq) {
return boxBool(false);
} else if (op_type == AST_TYPE::NotEq) {
return boxBool(true);
} else {
Box* r = compareInternal(lhs->elts->elts[i], rhs->elts->elts[i], op_type, NULL);
return r;
}
}
if (op_type == AST_TYPE::Lt)
return boxBool(lsz < rsz);
else if (op_type == AST_TYPE::LtE)
return boxBool(lsz <= rsz);
else if (op_type == AST_TYPE::Gt)
return boxBool(lsz > rsz);
else if (op_type == AST_TYPE::GtE)
return boxBool(lsz >= rsz);
else if (op_type == AST_TYPE::Eq)
return boxBool(lsz == rsz);
else if (op_type == AST_TYPE::NotEq)
return boxBool(lsz != rsz);
RELEASE_ASSERT(0, "%d", op_type);
}
Box* listEq(BoxedList* self, Box* rhs) {
if (rhs->cls != list_cls) {
return NotImplemented;
}
return _listCmp(self, static_cast<BoxedList*>(rhs), AST_TYPE::Eq);
}
void setupList() { void setupList() {
list_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedList), false); list_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedList), false);
...@@ -448,6 +496,8 @@ void setupList() { ...@@ -448,6 +496,8 @@ void setupList() {
list_cls->giveAttr("__iter__", list_cls->giveAttr("__iter__",
new BoxedFunction(boxRTFunction((void*)listIter, typeFromClass(list_iterator_cls), 1, false))); new BoxedFunction(boxRTFunction((void*)listIter, typeFromClass(list_iterator_cls), 1, false)));
list_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)listEq, NULL, 2, false)));
list_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)listRepr, STR, 1, false))); list_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)listRepr, STR, 1, false)));
list_cls->giveAttr("__str__", list_cls->getattr("__repr__")); list_cls->giveAttr("__str__", list_cls->getattr("__repr__"));
list_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)listNonzero, BOXED_BOOL, 1, false))); list_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)listNonzero, BOXED_BOOL, 1, false)));
...@@ -498,6 +548,8 @@ void setupList() { ...@@ -498,6 +548,8 @@ void setupList() {
CLFunction* hasnext = boxRTFunction((void*)listiterHasnextUnboxed, BOOL, 1, false); CLFunction* hasnext = boxRTFunction((void*)listiterHasnextUnboxed, BOOL, 1, false);
addRTFunction(hasnext, (void*)listiterHasnext, BOXED_BOOL, 1, false); addRTFunction(hasnext, (void*)listiterHasnext, BOXED_BOOL, 1, false);
list_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext)); list_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
list_iterator_cls->giveAttr(
"__iter__", new BoxedFunction(boxRTFunction((void*)listIterIter, typeFromClass(list_iterator_cls), 1, false)));
list_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)listiterNext, UNKNOWN, 1, false))); list_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)listiterNext, UNKNOWN, 1, false)));
list_iterator_cls->freeze(); list_iterator_cls->freeze();
......
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
namespace pyston { namespace pyston {
extern BoxedClass* list_iterator_cls; extern BoxedClass* list_iterator_cls;
struct BoxedListIterator : public Box { class BoxedListIterator : public Box {
public:
BoxedList* l; BoxedList* l;
int pos; int pos;
BoxedListIterator(BoxedList* l); BoxedListIterator(BoxedList* l);
...@@ -29,6 +30,7 @@ struct BoxedListIterator : public Box { ...@@ -29,6 +30,7 @@ struct BoxedListIterator : public Box {
extern "C" const ObjectFlavor list_iterator_flavor; extern "C" const ObjectFlavor list_iterator_flavor;
Box* listIter(Box* self); Box* listIter(Box* self);
Box* listIterIter(Box* self);
Box* listiterHasnext(Box* self); Box* listiterHasnext(Box* self);
i1 listiterHasnextUnboxed(Box* self); i1 listiterHasnextUnboxed(Box* self);
Box* listiterNext(Box* self); Box* listiterNext(Box* self);
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "runtime/tuple.h"
#include <sstream> #include <sstream>
#include "codegen/compvars.h" #include "codegen/compvars.h"
...@@ -19,6 +21,7 @@ ...@@ -19,6 +21,7 @@
#include "core/common.h" #include "core/common.h"
#include "core/stats.h" #include "core/stats.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h"
#include "runtime/gc_runtime.h" #include "runtime/gc_runtime.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
...@@ -187,12 +190,28 @@ Box* tupleHash(BoxedTuple* self) { ...@@ -187,12 +190,28 @@ Box* tupleHash(BoxedTuple* self) {
return boxInt(rtn); return boxInt(rtn);
} }
BoxedClass* tuple_iterator_cls = NULL;
extern "C" void tupleIteratorGCHandler(GCVisitor* v, void* p) {
boxGCHandler(v, p);
BoxedTupleIterator* it = (BoxedTupleIterator*)p;
v->visit(it->t);
}
extern "C" const ObjectFlavor tuple_iterator_flavor(&tupleIteratorGCHandler, NULL);
void setupTuple() { void setupTuple() {
tuple_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedTuple), false);
tuple_cls->giveAttr("__name__", boxStrConstant("tuple")); tuple_cls->giveAttr("__name__", boxStrConstant("tuple"));
tuple_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)tupleGetitem, NULL, 2, false))); tuple_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)tupleGetitem, NULL, 2, false)));
tuple_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)tupleContains, NULL, 2, false))); tuple_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)tupleContains, NULL, 2, false)));
tuple_cls->giveAttr("__iter__",
new BoxedFunction(boxRTFunction((void*)tupleIter, typeFromClass(tuple_iterator_cls), 1, false)));
tuple_cls->giveAttr("__lt__", new BoxedFunction(boxRTFunction((void*)tupleLt, NULL, 2, false))); tuple_cls->giveAttr("__lt__", new BoxedFunction(boxRTFunction((void*)tupleLt, NULL, 2, false)));
tuple_cls->giveAttr("__le__", new BoxedFunction(boxRTFunction((void*)tupleLe, NULL, 2, false))); tuple_cls->giveAttr("__le__", new BoxedFunction(boxRTFunction((void*)tupleLe, NULL, 2, false)));
tuple_cls->giveAttr("__gt__", new BoxedFunction(boxRTFunction((void*)tupleGt, NULL, 2, false))); tuple_cls->giveAttr("__gt__", new BoxedFunction(boxRTFunction((void*)tupleGt, NULL, 2, false)));
...@@ -206,8 +225,22 @@ void setupTuple() { ...@@ -206,8 +225,22 @@ void setupTuple() {
tuple_cls->giveAttr("__str__", tuple_cls->getattr("__repr__")); tuple_cls->giveAttr("__str__", tuple_cls->getattr("__repr__"));
tuple_cls->freeze(); tuple_cls->freeze();
gc::registerStaticRootObj(tuple_iterator_cls);
tuple_iterator_cls->giveAttr("__name__", boxStrConstant("tupleiterator"));
CLFunction* hasnext = boxRTFunction((void*)tupleiterHasnextUnboxed, BOOL, 1, false);
addRTFunction(hasnext, (void*)tupleiterHasnext, BOXED_BOOL, 1, false);
tuple_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
tuple_iterator_cls->giveAttr(
"__iter__", new BoxedFunction(boxRTFunction((void*)tupleIterIter, typeFromClass(tuple_iterator_cls), 1, false)));
tuple_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)tupleiterNext, UNKNOWN, 1, false)));
tuple_iterator_cls->freeze();
} }
void teardownTuple() { void teardownTuple() {
// TODO do clearattrs?
// decref(tuple_iterator_cls);
} }
} }
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_RUNTIME_TUPLE_H
#define PYSTON_RUNTIME_TUPLE_H
#include "core/types.h"
#include "runtime/types.h"
namespace pyston {
extern BoxedClass* tuple_iterator_cls;
class BoxedTupleIterator : public Box {
public:
BoxedTuple* t;
int pos;
BoxedTupleIterator(BoxedTuple* t);
};
extern "C" const ObjectFlavor tuple_iterator_flavor;
Box* tupleIter(Box* self);
Box* tupleIterIter(Box* self);
Box* tupleiterHasnext(Box* self);
i1 tupleiterHasnextUnboxed(Box* self);
Box* tupleiterNext(Box* self);
}
#endif
...@@ -301,7 +301,7 @@ Box* exceptionNew1(BoxedClass* cls); ...@@ -301,7 +301,7 @@ Box* exceptionNew1(BoxedClass* cls);
Box* exceptionNew2(BoxedClass* cls, Box* message); Box* exceptionNew2(BoxedClass* cls, Box* message);
extern BoxedClass* Exception, *AssertionError, *AttributeError, *TypeError, *NameError, *KeyError, *IndexError, extern BoxedClass* Exception, *AssertionError, *AttributeError, *TypeError, *NameError, *KeyError, *IndexError,
*IOError, *OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError, *RuntimeError, *ImportError; *IOError, *OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError, *RuntimeError, *ImportError, *StopIteration;
// cls should be obj->cls. // cls should be obj->cls.
// Added as parameter because it should typically be available // Added as parameter because it should typically be available
......
...@@ -14,3 +14,45 @@ assert iter_b.next() == 2 ...@@ -14,3 +14,45 @@ assert iter_b.next() == 2
assert iter_b.next() == 'a' assert iter_b.next() == 'a'
assert iter_b.next() == (3, 2) assert iter_b.next() == (3, 2)
assert type(a) == list
# __eq__ tests
assert [3, 2, 1] == [3, 2, 1]
assert [3, 2, 1] == list(a)
assert [3, 2, ['a']] == list([3, 2, ['a']])
assert [3, 2, ['a', 2]] == list([3, 2, ['a', 2]])
class A(object):
pass
a_class = A()
assert [3, 2, ['a', 2]] == list([3, 2, ['a', 2]])
#
new_a = []
for i in a:
new_a.append(i)
assert [3, 2, 1] == new_a
# __iter__s
assert [3, 2, 1] == list(a.__iter__())
new_a = []
for i in a.__iter__():
new_a.append(i)
assert [3, 2, 1] == new_a
# StopIteration exception
try:
iter_a.next()
assert False, "next() called without StopIteration"
except StopIteration:
assert True
a = (3, 2, 1)
b = (2, 'a', (3, 2))
# TODO: uncomment when hassattr will be implemented
#assert hasattr(a, '__iter__')
iter_a = a.__iter__()
assert iter_a.next() == 3
assert iter_a.next() == 2
assert iter_a.next() == 1
iter_b = b.__iter__()
assert iter_b.next() == 2
assert iter_b.next() == 'a'
assert iter_b.next() == (3, 2)
assert type(a) == tuple
#
omglist = list(a)
assert omglist == [3, 2, 1]
assert [3, 2, 1] == list(a)
new_a = []
for i in a:
new_a.append(i)
assert [3, 2, 1] == new_a
# __iter__s
assert [3, 2, 1] == list(a.__iter__())
new_a = []
for i in a.__iter__():
new_a.append(i)
assert [3, 2, 1] == new_a
# StopIteration exception
try:
iter_a.next()
assert False, "next() called without StopIteration"
except StopIteration:
assert True
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