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;
// TODO looks like CPython and pypy put this into an "exceptions" module:
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);
Box* exceptionNew1(BoxedClass* cls) {
......@@ -440,6 +440,7 @@ void setupBuiltins() {
UnboundLocalError = makeBuiltinException(Exception, "UnboundLocalError");
RuntimeError = makeBuiltinException(Exception, "RuntimeError");
ImportError = makeBuiltinException(Exception, "ImportError");
StopIteration = makeBuiltinException(Exception, "StopIteration");
repr_obj = new BoxedFunction(boxRTFunction((void*)repr, NULL, 1, false));
builtins_module->giveAttr("repr", repr_obj);
......
......@@ -21,7 +21,8 @@
namespace pyston {
extern BoxedClass* dict_iterator_cls;
struct BoxedDictIterator : public Box {
class BoxedDictIterator : public Box {
public:
enum IteratorType { KeyIterator, ValueIterator, ItemIterator };
BoxedDict* d;
......
......@@ -16,6 +16,7 @@
#include <cstring>
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h"
#include "runtime/list.h"
namespace pyston {
......@@ -23,6 +24,11 @@ namespace pyston {
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) {
assert(s->cls == list_cls);
BoxedList* self = static_cast<BoxedList*>(s);
......@@ -47,7 +53,10 @@ Box* listiterNext(Box* s) {
assert(s->cls == list_iterator_cls);
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];
self->pos++;
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) {
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() {
list_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedList), false);
......@@ -448,6 +496,8 @@ void setupList() {
list_cls->giveAttr("__iter__",
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("__str__", list_cls->getattr("__repr__"));
list_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)listNonzero, BOXED_BOOL, 1, false)));
......@@ -498,6 +548,8 @@ void setupList() {
CLFunction* hasnext = boxRTFunction((void*)listiterHasnextUnboxed, BOOL, 1, false);
addRTFunction(hasnext, (void*)listiterHasnext, BOXED_BOOL, 1, false);
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->freeze();
......
......@@ -21,7 +21,8 @@
namespace pyston {
extern BoxedClass* list_iterator_cls;
struct BoxedListIterator : public Box {
class BoxedListIterator : public Box {
public:
BoxedList* l;
int pos;
BoxedListIterator(BoxedList* l);
......@@ -29,6 +30,7 @@ struct BoxedListIterator : public Box {
extern "C" const ObjectFlavor list_iterator_flavor;
Box* listIter(Box* self);
Box* listIterIter(Box* self);
Box* listiterHasnext(Box* self);
i1 listiterHasnextUnboxed(Box* self);
Box* listiterNext(Box* self);
......
......@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "runtime/tuple.h"
#include <sstream>
#include "codegen/compvars.h"
......@@ -19,6 +21,7 @@
#include "core/common.h"
#include "core/stats.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/gc_runtime.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......@@ -187,12 +190,28 @@ Box* tupleHash(BoxedTuple* self) {
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() {
tuple_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedTuple), false);
tuple_cls->giveAttr("__name__", boxStrConstant("tuple"));
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("__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("__le__", new BoxedFunction(boxRTFunction((void*)tupleLe, NULL, 2, false)));
tuple_cls->giveAttr("__gt__", new BoxedFunction(boxRTFunction((void*)tupleGt, NULL, 2, false)));
......@@ -206,8 +225,22 @@ void setupTuple() {
tuple_cls->giveAttr("__str__", tuple_cls->getattr("__repr__"));
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() {
// 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);
Box* exceptionNew2(BoxedClass* cls, Box* message);
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.
// Added as parameter because it should typically be available
......
......@@ -14,3 +14,45 @@ assert iter_b.next() == 2
assert iter_b.next() == 'a'
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