Commit 7662ccb2 authored by Marius Wachtler's avatar Marius Wachtler

Reduce code duplication with a template

parent f6c70e2e
...@@ -12,155 +12,128 @@ ...@@ -12,155 +12,128 @@
// 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/iterators.h" #include "core/types.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h"
namespace pyston { namespace pyston {
namespace {
llvm::iterator_range<BoxIterator> BoxIterator::getRange(Box* container) { static std::string next_str("next");
if (container->cls == list_cls) {
BoxIterator begin(std::make_shared<BoxIteratorList>(container));
static BoxIterator end(std::make_shared<BoxIteratorList>(BoxIteratorList::end()));
return llvm::iterator_range<BoxIterator>(std::move(begin), end);
} else if (container->cls == tuple_cls) {
BoxIterator begin(std::make_shared<BoxIteratorTuple>(container));
static BoxIterator end(std::make_shared<BoxIteratorTuple>(BoxIteratorTuple::end()));
return llvm::iterator_range<BoxIterator>(std::move(begin), end);
} else if (container->cls == str_cls) {
BoxIterator begin(std::make_shared<BoxIteratorString>(container));
static BoxIterator end(std::make_shared<BoxIteratorString>(BoxIteratorString::end()));
return llvm::iterator_range<BoxIterator>(std::move(begin), end);
}
BoxIterator begin(std::make_shared<BoxIteratorGeneric>(container));
static BoxIterator end(std::make_shared<BoxIteratorGeneric>(BoxIteratorGeneric::end()));
return llvm::iterator_range<BoxIterator>(std::move(begin), end);
}
BoxIteratorGeneric::BoxIteratorGeneric(Box* container) : BoxIteratorImpl(container), iterator(nullptr), value(nullptr) { class BoxIteratorGeneric : public BoxIteratorImpl {
if (container) { private:
// TODO: this should probably call getPystonIter Box* iterator;
iterator = getiter(container); Box* value;
if (iterator)
next(); public:
else BoxIteratorGeneric(Box* container) : BoxIteratorImpl(container), iterator(nullptr), value(nullptr) {
*this = end(); if (container) {
// TODO: this should probably call getPystonIter
iterator = getiter(container);
if (iterator)
next();
else
*this = end();
}
} }
}
static std::string next_str("next"); void next() override {
void BoxIteratorGeneric::next() { assert(iterator);
assert(iterator); Box* hasnext = iterator->hasnextOrNullIC();
Box* hasnext = iterator->hasnextOrNullIC(); if (hasnext) {
if (hasnext) { if (hasnext->nonzeroIC()) {
if (hasnext->nonzeroIC()) { value = iterator->nextIC();
value = iterator->nextIC(); } else {
} else {
*this = end();
}
} else {
try {
value = iterator->nextIC();
} catch (ExcInfo e) {
if (e.matches(StopIteration))
*this = end(); *this = end();
else }
throw e; } else {
try {
value = iterator->nextIC();
} catch (ExcInfo e) {
if (e.matches(StopIteration))
*this = end();
else
throw e;
}
} }
} }
}
bool BoxIteratorGeneric::isSame(const BoxIteratorImpl* _rhs) {
BoxIteratorGeneric* rhs = (BoxIteratorGeneric*)_rhs;
return iterator == rhs->iterator && value == rhs->value;
}
void BoxIteratorGeneric::gcHandler(GCVisitor* v) { Box* getValue() override { return value; }
v->visitPotential(iterator);
v->visitPotential(value);
}
BoxIteratorList::BoxIteratorList(Box* container) : BoxIteratorImpl(container), list((BoxedList*)container), index(0) { void gcHandler(GCVisitor* v) override {
assert(!container || container->cls == list_cls); v->visitPotential(iterator);
if (list && index >= list->size) v->visitPotential(value);
*this = end(); }
}
void BoxIteratorList::next() { bool isSame(const BoxIteratorImpl* _rhs) override {
if (!end().isSame(this)) { BoxIteratorGeneric* rhs = (BoxIteratorGeneric*)_rhs;
++index; return iterator == rhs->iterator && value == rhs->value;
if (index >= list->size)
*this = end();
} }
}
Box* BoxIteratorList::getValue() { static BoxIteratorGeneric end() { return BoxIteratorGeneric(nullptr); }
return list->elts->elts[index]; };
}
void BoxIteratorList::gcHandler(GCVisitor* v) { template <typename T> class BoxIteratorIndex : public BoxIteratorImpl {
v->visitPotential(list); private:
} T* obj;
uint64_t index;
bool BoxIteratorList::isSame(const BoxIteratorImpl* _rhs) { static bool hasnext(BoxedList* o, uint64_t i) { return i < o->size; }
BoxIteratorList* rhs = (BoxIteratorList*)_rhs; static Box* getValue(BoxedList* o, uint64_t i) { return o->elts->elts[i]; }
return list == rhs->list && index == rhs->index;
}
BoxIteratorTuple::BoxIteratorTuple(Box* container) static bool hasnext(BoxedTuple* o, uint64_t i) { return i < o->elts.size(); }
: BoxIteratorImpl(container), tuple((BoxedTuple*)container), index(0) { static Box* getValue(BoxedTuple* o, uint64_t i) { return o->elts[i]; }
assert(!container || container->cls == tuple_cls);
if (tuple && index >= tuple->elts.size())
*this = end();
}
void BoxIteratorTuple::next() { static bool hasnext(BoxedString* o, uint64_t i) { return i < o->s.size(); }
if (!end().isSame(this)) { static Box* getValue(BoxedString* o, uint64_t i) { return new BoxedString(std::string(1, o->s[i])); }
++index;
if (index >= tuple->elts.size()) public:
BoxIteratorIndex(T* obj) : BoxIteratorImpl(obj), obj(obj), index(0) {
if (obj && !hasnext(obj, index))
*this = end(); *this = end();
} }
}
Box* BoxIteratorTuple::getValue() { void next() override {
return tuple->elts[index]; if (!end().isSame(this)) {
} ++index;
if (!hasnext(obj, index))
void BoxIteratorTuple::gcHandler(GCVisitor* v) { *this = end();
v->visitPotential(tuple); }
} }
bool BoxIteratorTuple::isSame(const BoxIteratorImpl* _rhs) { Box* getValue() override { return getValue(obj, index); }
BoxIteratorTuple* rhs = (BoxIteratorTuple*)_rhs;
return tuple == rhs->tuple && index == rhs->index;
}
BoxIteratorString::BoxIteratorString(Box* container) void gcHandler(GCVisitor* v) override { v->visitPotential(obj); }
: BoxIteratorImpl(container), string((BoxedString*)container), index(0) {
assert(!container || container->cls == str_cls);
if (string && index >= string->s.size())
*this = end();
}
void BoxIteratorString::next() { bool isSame(const BoxIteratorImpl* _rhs) override {
if (!end().isSame(this)) { auto rhs = (BoxIteratorIndex*)_rhs;
++index; return obj == rhs->obj && index == rhs->index;
if (index >= string->s.size())
*this = end();
} }
}
Box* BoxIteratorString::getValue() {
return new BoxedString(std::string(1, string->s[index]));
}
void BoxIteratorString::gcHandler(GCVisitor* v) { static BoxIteratorIndex end() { return BoxIteratorIndex(nullptr); }
v->visitPotential(string); };
} }
bool BoxIteratorString::isSame(const BoxIteratorImpl* _rhs) { llvm::iterator_range<BoxIterator> BoxIterator::getRange(Box* container) {
BoxIteratorString* rhs = (BoxIteratorString*)_rhs; if (container->cls == list_cls) {
return string == rhs->string && index == rhs->index; using BoxIteratorList = BoxIteratorIndex<BoxedList>;
BoxIterator begin(std::make_shared<BoxIteratorIndex<BoxedList>>((BoxedList*)container));
static BoxIterator end(std::make_shared<BoxIteratorIndex<BoxedList>>(BoxIteratorList::end()));
return llvm::iterator_range<BoxIterator>(std::move(begin), end);
} else if (container->cls == tuple_cls) {
using BoxIteratorTuple = BoxIteratorIndex<BoxedTuple>;
BoxIterator begin(std::make_shared<BoxIteratorIndex<BoxedTuple>>((BoxedTuple*)container));
static BoxIterator end(std::make_shared<BoxIteratorIndex<BoxedTuple>>(BoxIteratorTuple::end()));
return llvm::iterator_range<BoxIterator>(std::move(begin), end);
} else if (container->cls == str_cls) {
using BoxIteratorString = BoxIteratorIndex<BoxedString>;
BoxIterator begin(std::make_shared<BoxIteratorIndex<BoxedString>>((BoxedString*)container));
static BoxIterator end(std::make_shared<BoxIteratorIndex<BoxedString>>(BoxIteratorString::end()));
return llvm::iterator_range<BoxIterator>(std::move(begin), end);
}
BoxIterator begin(std::make_shared<BoxIteratorGeneric>(container));
static BoxIterator end(std::make_shared<BoxIteratorGeneric>(BoxIteratorGeneric::end()));
return llvm::iterator_range<BoxIterator>(std::move(begin), end);
} }
} }
// Copyright (c) 2014-2015 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_ITERATORS_H
#define PYSTON_RUNTIME_ITERATORS_H
#include "core/types.h"
#include "runtime/types.h"
namespace pyston {
class BoxIteratorGeneric : public BoxIteratorImpl {
private:
Box* iterator;
Box* value;
public:
BoxIteratorGeneric(Box* container);
void next() override;
Box* getValue() override { return value; }
void gcHandler(GCVisitor* v) override;
bool isSame(const BoxIteratorImpl* rhs) override;
static BoxIteratorGeneric end() { return BoxIteratorGeneric(nullptr); }
};
class BoxIteratorList : public BoxIteratorImpl {
private:
BoxedList* list;
int64_t index;
public:
BoxIteratorList(Box* list);
void next() override;
Box* getValue() override;
void gcHandler(GCVisitor* v) override;
bool isSame(const BoxIteratorImpl* rhs) override;
static BoxIteratorList end() { return BoxIteratorList(nullptr); }
};
class BoxIteratorTuple : public BoxIteratorImpl {
private:
BoxedTuple* tuple;
int64_t index;
public:
BoxIteratorTuple(Box* tuple);
void next() override;
Box* getValue() override;
void gcHandler(GCVisitor* v) override;
bool isSame(const BoxIteratorImpl* rhs) override;
static BoxIteratorTuple end() { return BoxIteratorTuple(nullptr); }
};
class BoxIteratorString : public BoxIteratorImpl {
private:
BoxedString* string;
int64_t index;
public:
BoxIteratorString(Box* string);
void next() override;
Box* getValue() override;
void gcHandler(GCVisitor* v) override;
bool isSame(const BoxIteratorImpl* rhs) override;
static BoxIteratorString end() { return BoxIteratorString(nullptr); }
};
}
#endif
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