From 76e7746d25ed1ed157c2faf9ac3d068d95a8c48b Mon Sep 17 00:00:00 2001 From: "S. Mahmudul Hasan" Date: Tue, 10 Oct 2023 13:43:02 -0400 Subject: [PATCH] WIP: Added more functionalities in deque --- include/pocketpy/collections.h | 35 +++++------ src/collections.cpp | 102 +++++++++++++++++++++++++++------ 2 files changed, 99 insertions(+), 38 deletions(-) diff --git a/include/pocketpy/collections.h b/include/pocketpy/collections.h index 7e54f170..b01f9635 100644 --- a/include/pocketpy/collections.h +++ b/include/pocketpy/collections.h @@ -108,19 +108,6 @@ namespace pkpy return false; } - int count(VM *vm, PyObject *obj) - { - int cnt = 0; - DequeNode *p = this->head->next; - while (p != this->tail) - { - if (vm->py_equals(p->obj, obj)) - cnt++; - p = p->next; - } - return cnt; - } - int size() const { return this->len; @@ -136,19 +123,24 @@ namespace pkpy void reverse() { - DequeNode *p = this->head->next; - while (p != this->tail) - { + 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; } - DequeNode *tmp = this->head->next; - this->head->next = this->tail->prev; - this->tail->prev = tmp; - } + // swap the head and tail pointers + DequeNode *tmp = this->head; + this->head = this->tail; + this->tail = tmp; + } + }; // STARTING HERE @@ -165,10 +157,11 @@ 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 count(VM *vm, PyObject *obj); // vm is needed for the py_equals void clear(); - + PyDeque() : dequeItems(new MyDoublyLinkedList()) {} static void _register(VM *vm, PyObject *mod, PyObject *type); diff --git a/src/collections.cpp b/src/collections.cpp index 87e61955..f510a86f 100644 --- a/src/collections.cpp +++ b/src/collections.cpp @@ -5,6 +5,19 @@ namespace pkpy void PyDeque::_register(VM *vm, PyObject *mod, PyObject *type) { vm->bind_default_constructor(type); + + vm->bind(type, "__init__(self) -> None", + [](VM *vm, ArgsView args) + { + PyDeque &self = _CAST(PyDeque &, args[0]); + PyObject *maxlen = args[1]; + if (maxlen != vm->None) + { + // printf("TODO: implement deque.__init__(maxlen) -> None: %d\n", CAST(int, maxlen)); + } + + return vm->None; + }); vm->bind(type, "__len__(self) -> int", [](VM *vm, ArgsView args) @@ -42,12 +55,15 @@ namespace pkpy vm->bind(type, "copy(self) -> deque", [](VM *vm, ArgsView args) { - // followed implementation of dict.copy() - // PyDeque &self = _CAST(PyDeque &, args[0]); - // return VAR(self); - //todo: implement - printf("TODO: implement deque.copy()"); - 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", @@ -89,12 +105,20 @@ namespace pkpy return vm->None; }); - vm->bind(type, "index(self, obj, start=0, stop=None) -> int", + vm->bind(type, "index(self, obj, start=-1, stop=-1) -> int", [](VM *vm, ArgsView args) { - // TODO: implement and validate - printf("TODO: implement deque.index()"); - return vm->None; + // Return the position of x in the deque (at or after index start and before index stop). Returns the first match or raises ValueError if not found. + PyDeque &self = _CAST(PyDeque &, args[0]); + PyObject *obj = args[1]; + int start = CAST(int, args[2]); + int stop = CAST(int, args[3]); + int idx = self.findIndex(obj, start, stop); + + if (idx == -1) + vm->ValueError(_CAST(Str &, vm->py_repr(obj)) + " is not in list"); + + return VAR(idx); }); vm->bind(type, "insert(self, index, obj) -> None", @@ -143,14 +167,14 @@ namespace pkpy self.reverse(); return vm->None; }); - vm->bind(type,"rotate(self, n=1) -> None", + vm->bind(type, "rotate(self, n=1) -> None", [](VM *vm, ArgsView args) { - //TODO: implement and validate - printf("TODO: implement deque.rotate()"); - return vm->None; + // TODO: implement and validate + printf("TODO: implement deque.rotate()"); + return vm->None; }); - + // vm->bind(type,"maxlen", // [](VM *vm, ArgsView args) // { @@ -160,7 +184,12 @@ namespace pkpy void PyDeque::_gc_mark() const { - // TODO: implement + 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; + } } std::stringstream PyDeque::getRepr(VM *vm) { @@ -178,6 +207,37 @@ namespace pkpy return ss; } + int PyDeque::findIndex(PyObject *obj, int startPos = -1, int endPos = -1) + { + + if (startPos == -1) + startPos = 0; + if (endPos == -1) + 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) + { + if (p->obj == obj) + { + if (startPos == -1 || cnt >= startPos) + { + if (endPos == -1 || cnt < endPos) + { + return cnt; + } + } + } + cnt++; + p = p->next; + } + return -1; + } void PyDeque::reverse() { this->dequeItems->reverse(); @@ -216,7 +276,15 @@ namespace pkpy int PyDeque::count(VM *vm, PyObject *obj) { - return this->dequeItems->count(vm, obj); + int cnt = 0; + DequeNode *p = this->dequeItems->head->next; + while (p != this->dequeItems->tail) + { + if (vm->py_equals(p->obj, obj)) + cnt++; + p = p->next; + } + return cnt; } void PyDeque::clear() {