diff --git a/include/pocketpy/collections.h b/include/pocketpy/collections.h index b01f9635..6273cf4e 100644 --- a/include/pocketpy/collections.h +++ b/include/pocketpy/collections.h @@ -6,142 +6,143 @@ #include "str.h" #include "iter.h" #include "cffi.h" +#include namespace pkpy { - struct DequeNode - { - PyObject *obj; - DequeNode *prev; - DequeNode *next; - DequeNode() - { - this->obj = nullptr; // ignored value, sentinnel - this->prev = nullptr; - this->next = nullptr; - } - DequeNode(PyObject *obj) - { - this->obj = obj; - this->prev = nullptr; - this->next = nullptr; - } + // struct DequeNode + // { + // PyObject *obj; + // DequeNode *prev; + // DequeNode *next; + // DequeNode() + // { + // this->obj = nullptr; // ignored value, sentinnel + // this->prev = nullptr; + // this->next = nullptr; + // } + // DequeNode(PyObject *obj) + // { + // this->obj = obj; + // this->prev = nullptr; + // this->next = nullptr; + // } - ~DequeNode() - { - } - }; + // ~DequeNode() + // { + // } + // }; - struct MyDoublyLinkedList - { - int len; - DequeNode *head; - DequeNode *tail; + // struct MyDoublyLinkedList + // { + // int len; + // DequeNode *head; + // DequeNode *tail; - MyDoublyLinkedList() - { // creates an empty list - this->len = 0; - this->head = new DequeNode(); // dummy - this->tail = new DequeNode(); // dummy - this->head->next = this->tail; - this->tail->prev = this->head; - } + // MyDoublyLinkedList() + // { // creates an empty list + // this->len = 0; + // this->head = new DequeNode(); // dummy + // this->tail = new DequeNode(); // dummy + // this->head->next = this->tail; + // this->tail->prev = this->head; + // } - ~MyDoublyLinkedList() - { - if (this->head == nullptr) - return; - this->makeListEmpty(); - delete this->head; - delete this->tail; - } + // ~MyDoublyLinkedList() + // { + // if (this->head == nullptr) + // return; + // this->makeListEmpty(); + // delete this->head; + // delete this->tail; + // } - void push_back(DequeNode *node) - { - node->prev = this->tail->prev; - node->next = this->tail; - this->tail->prev->next = node; - this->tail->prev = node; - this->len++; - } - void push_front(DequeNode *node) - { - node->prev = this->head; - node->next = this->head->next; - this->head->next->prev = node; - this->head->next = node; - this->len++; - } + // void push_back(DequeNode *node) + // { + // node->prev = this->tail->prev; + // node->next = this->tail; + // this->tail->prev->next = node; + // this->tail->prev = node; + // this->len++; + // } + // void push_front(DequeNode *node) + // { + // node->prev = this->head; + // node->next = this->head->next; + // this->head->next->prev = node; + // this->head->next = node; + // this->len++; + // } - DequeNode *pop_back() - { - if (this->empty()) - throw std::runtime_error("DoubleLinkedList::pop_back() called on empty list"); - DequeNode *node = this->tail->prev; - this->tail->prev->prev->next = this->tail; - this->tail->prev = this->tail->prev->prev; - this->len--; - return node; - } + // DequeNode *pop_back() + // { + // if (this->empty()) + // throw std::runtime_error("DoubleLinkedList::pop_back() called on empty list"); + // DequeNode *node = this->tail->prev; + // this->tail->prev->prev->next = this->tail; + // this->tail->prev = this->tail->prev->prev; + // this->len--; + // return node; + // } - DequeNode *pop_front() - { - if (this->empty()) - throw std::runtime_error("DoubleLinkedList::pop_front() called on empty list"); - DequeNode *node = this->head->next; - this->head->next->next->prev = this->head; - this->head->next = this->head->next->next; - this->len--; - return node; - } + // DequeNode *pop_front() + // { + // if (this->empty()) + // throw std::runtime_error("DoubleLinkedList::pop_front() called on empty list"); + // DequeNode *node = this->head->next; + // this->head->next->next->prev = this->head; + // this->head->next = this->head->next->next; + // this->len--; + // return node; + // } - bool empty() const - { - if (this->len == 0) - { - if (this->head->next != this->tail || this->tail->prev != this->head) - { - throw std::runtime_error("DoubleLinkedList::size() returned 0 but the list is not empty"); - } - return true; - } - return false; - } + // bool empty() const + // { + // if (this->len == 0) + // { + // if (this->head->next != this->tail || this->tail->prev != this->head) + // { + // throw std::runtime_error("DoubleLinkedList::size() returned 0 but the list is not empty"); + // } + // return true; + // } + // return false; + // } - int size() const - { - return this->len; - } + // int size() const + // { + // return this->len; + // } - void makeListEmpty() - { - while (!this->empty()) - { - this->pop_back(); - } - } + // void makeListEmpty() + // { + // while (!this->empty()) + // { + // this->pop_back(); + // } + // } - void reverse() - { - if (this->empty()) - return; - // Go through each node, including the dummy nodes - // and swap the prev and next pointers - DequeNode *p = this->head; - while (p!=nullptr){ - DequeNode *tmp = p->next; - p->next = p->prev; - p->prev = tmp; - p = tmp; - } + // void reverse() + // { + // if (this->empty()) + // return; + // // Go through each node, including the dummy nodes + // // and swap the prev and next pointers + // DequeNode *p = this->head; + // while (p!=nullptr){ + // DequeNode *tmp = p->next; + // p->next = p->prev; + // p->prev = tmp; + // p = tmp; + // } - // swap the head and tail pointers - DequeNode *tmp = this->head; - this->head = this->tail; - this->tail = tmp; - } + // // swap the head and tail pointers + // DequeNode *tmp = this->head; + // this->head = this->tail; + // this->tail = tmp; + // } - }; + // }; // STARTING HERE struct PyDeque @@ -149,7 +150,8 @@ namespace pkpy PY_CLASS(PyDeque, mycollections, deque); // some fields can be defined here - MyDoublyLinkedList *dequeItems; + + std::dequedequeItems; void appendLeft(PyObject *item); void append(PyObject *item); @@ -157,12 +159,12 @@ namespace pkpy PyObject *pop(); std::stringstream getRepr(VM *vm); void reverse(); - int findIndex(PyObject *obj, int startPos, int endPos); // vm is needed for the py_equals + int findIndex(VM *vm, PyObject *obj, int startPos, int endPos); // vm is needed for the py_equals int count(VM *vm, PyObject *obj); // vm is needed for the py_equals void clear(); - PyDeque() : dequeItems(new MyDoublyLinkedList()) {} + PyDeque(){} static void _register(VM *vm, PyObject *mod, PyObject *type); void _gc_mark() const; // needed for container types diff --git a/src/collections.cpp b/src/collections.cpp index f510a86f..c9bd1825 100644 --- a/src/collections.cpp +++ b/src/collections.cpp @@ -23,7 +23,7 @@ namespace pkpy [](VM *vm, ArgsView args) { PyDeque &self = _CAST(PyDeque &, args[0]); - return VAR(self.dequeItems->size()); + return VAR(self.dequeItems.size()); }); vm->bind(type, "append(self, item) -> None", @@ -55,15 +55,17 @@ namespace pkpy vm->bind(type, "copy(self) -> deque", [](VM *vm, ArgsView args) { - PyDeque &self = _CAST(PyDeque &, args[0]); - PyDeque *newDeque = new PyDeque(); - DequeNode *p = self.dequeItems->head->next; - while (p != self.dequeItems->tail) - { - newDeque->append(p->obj); - p = p->next; - } - return vm->heap.gcnew(PyDeque::_type(vm), *newDeque); + //TODO: implement and validate + return vm->None; + // PyDeque &self = _CAST(PyDeque &, args[0]); + // PyDeque *newDeque = new PyDeque(); + // DequeNode *p = self.dequeItems->head->next; + // while (p != self.dequeItems->tail) + // { + // newDeque->append(p->obj); + // p = p->next; + // } + // return vm->heap.gcnew(PyDeque::_type(vm), *newDeque); }); vm->bind(type, "count(self, obj) -> int", @@ -113,7 +115,7 @@ namespace pkpy PyObject *obj = args[1]; int start = CAST(int, args[2]); int stop = CAST(int, args[3]); - int idx = self.findIndex(obj, start, stop); + int idx = self.findIndex(vm, obj, start, stop); if (idx == -1) vm->ValueError(_CAST(Str &, vm->py_repr(obj)) + " is not in list"); @@ -184,111 +186,111 @@ namespace pkpy void PyDeque::_gc_mark() const { - DequeNode *p = this->dequeItems->head->next; - while (p != this->dequeItems->tail) - { - PK_OBJ_MARK(p->obj); // PK_OBJ_MARK is a macro that calls _gc_mark on the PK_OBJ - p = p->next; - } + //TODO: HOW TO IMPLEMENT THIS? } + + std::stringstream PyDeque::getRepr(VM *vm) { std::stringstream ss; + int sz = this->dequeItems.size(); ss << "deque(["; - DequeNode *p = this->dequeItems->head->next; - while (p != this->dequeItems->tail) + for (auto it = this->dequeItems.begin(); it != this->dequeItems.end(); ++it) { - ss << CAST(Str &, vm->py_repr(p->obj)); - if (p->next != this->dequeItems->tail) + ss << CAST(Str &, vm->py_repr(*it)); + if (it != this->dequeItems.end() - 1) + { ss << ", "; - p = p->next; + } } ss << "])"; return ss; } - int PyDeque::findIndex(PyObject *obj, int startPos = -1, int endPos = -1) + int PyDeque::findIndex(VM *vm, PyObject *obj, int startPos = -1, int endPos = -1) { if (startPos == -1) startPos = 0; if (endPos == -1) - endPos = this->dequeItems->size(); + endPos = this->dequeItems.size(); if (!(startPos <= endPos)) { throw std::runtime_error("startPos<=endPos"); } - int cnt = 0; - DequeNode *p = this->dequeItems->head->next; - while (p != this->dequeItems->tail) + int dequeSize = this->dequeItems.size(); + + for (int i = startPos; iobj == obj) + if (vm->py_equals(this->dequeItems[i], obj)) { - if (startPos == -1 || cnt >= startPos) - { - if (endPos == -1 || cnt < endPos) - { - return cnt; - } - } + return i; } - cnt++; - p = p->next; } return -1; } + + void PyDeque::reverse() { - this->dequeItems->reverse(); + int sz = this->dequeItems.size(); + for (int i = 0; i < sz / 2; i++) + { + PyObject *tmp = this->dequeItems[i]; + this->dequeItems[i] = this->dequeItems[sz - i - 1]; + this->dequeItems[sz - i - 1] = tmp; + } } void PyDeque::appendLeft(PyObject *item) { - DequeNode *node = new DequeNode(item); - this->dequeItems->push_front(node); + this->dequeItems.emplace_front(item); } void PyDeque::append(PyObject *item) { - DequeNode *node = new DequeNode(item); - this->dequeItems->push_back(node); + this->dequeItems.emplace_back(item); } PyObject *PyDeque::popLeft() { - if (this->dequeItems->empty()) + if (this->dequeItems.empty()) { throw std::runtime_error("pop from an empty deque"); } - DequeNode *node = this->dequeItems->pop_front(); - return node->obj; + PyObject *obj = this->dequeItems.front(); + this->dequeItems.pop_front(); + return obj; } PyObject *PyDeque::pop() { - if (this->dequeItems->empty()) + if (this->dequeItems.empty()) { throw std::runtime_error("pop from an empty deque"); } - DequeNode *node = this->dequeItems->pop_back(); - return node->obj; + PyObject *obj = this->dequeItems.back(); + this->dequeItems.pop_back(); + return obj; } int PyDeque::count(VM *vm, PyObject *obj) { int cnt = 0; - DequeNode *p = this->dequeItems->head->next; - while (p != this->dequeItems->tail) + + for (auto it = this->dequeItems.begin(); it != this->dequeItems.end(); ++it) { - if (vm->py_equals(p->obj, obj)) + if (vm->py_equals((*it), obj)) + { cnt++; - p = p->next; + } } return cnt; } + void PyDeque::clear() { - this->dequeItems->makeListEmpty(); + this->dequeItems.clear(); } void add_module_mycollections(VM *vm)