WIP: Added more functionalities in deque

This commit is contained in:
S. Mahmudul Hasan 2023-10-10 13:43:02 -04:00
parent 836f0506fa
commit 76e7746d25
2 changed files with 99 additions and 38 deletions

View File

@ -108,19 +108,6 @@ namespace pkpy
return false; 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 int size() const
{ {
return this->len; return this->len;
@ -136,19 +123,24 @@ namespace pkpy
void reverse() void reverse()
{ {
DequeNode *p = this->head->next; if (this->empty())
while (p != this->tail) 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; DequeNode *tmp = p->next;
p->next = p->prev; p->next = p->prev;
p->prev = tmp; p->prev = tmp;
p = 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 // STARTING HERE
@ -165,10 +157,11 @@ namespace pkpy
PyObject *pop(); PyObject *pop();
std::stringstream getRepr(VM *vm); std::stringstream getRepr(VM *vm);
void reverse(); 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 int count(VM *vm, PyObject *obj); // vm is needed for the py_equals
void clear(); void clear();
PyDeque() : dequeItems(new MyDoublyLinkedList()) {} PyDeque() : dequeItems(new MyDoublyLinkedList()) {}
static void _register(VM *vm, PyObject *mod, PyObject *type); static void _register(VM *vm, PyObject *mod, PyObject *type);

View File

@ -5,6 +5,19 @@ namespace pkpy
void PyDeque::_register(VM *vm, PyObject *mod, PyObject *type) void PyDeque::_register(VM *vm, PyObject *mod, PyObject *type)
{ {
vm->bind_default_constructor<PyDeque>(type); vm->bind_default_constructor<PyDeque>(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->bind(type, "__len__(self) -> int",
[](VM *vm, ArgsView args) [](VM *vm, ArgsView args)
@ -42,12 +55,15 @@ namespace pkpy
vm->bind(type, "copy(self) -> deque", vm->bind(type, "copy(self) -> deque",
[](VM *vm, ArgsView args) [](VM *vm, ArgsView args)
{ {
// followed implementation of dict.copy() PyDeque &self = _CAST(PyDeque &, args[0]);
// PyDeque &self = _CAST(PyDeque &, args[0]); PyDeque *newDeque = new PyDeque();
// return VAR(self); DequeNode *p = self.dequeItems->head->next;
//todo: implement while (p != self.dequeItems->tail)
printf("TODO: implement deque.copy()"); {
return vm->None; newDeque->append(p->obj);
p = p->next;
}
return vm->heap.gcnew<PyDeque>(PyDeque::_type(vm), *newDeque);
}); });
vm->bind(type, "count(self, obj) -> int", vm->bind(type, "count(self, obj) -> int",
@ -89,12 +105,20 @@ namespace pkpy
return vm->None; 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) [](VM *vm, ArgsView args)
{ {
// TODO: implement and validate // 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.
printf("TODO: implement deque.index()"); PyDeque &self = _CAST(PyDeque &, args[0]);
return vm->None; 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", vm->bind(type, "insert(self, index, obj) -> None",
@ -143,14 +167,14 @@ namespace pkpy
self.reverse(); self.reverse();
return vm->None; return vm->None;
}); });
vm->bind(type,"rotate(self, n=1) -> None", vm->bind(type, "rotate(self, n=1) -> None",
[](VM *vm, ArgsView args) [](VM *vm, ArgsView args)
{ {
//TODO: implement and validate // TODO: implement and validate
printf("TODO: implement deque.rotate()"); printf("TODO: implement deque.rotate()");
return vm->None; return vm->None;
}); });
// vm->bind(type,"maxlen", // vm->bind(type,"maxlen",
// [](VM *vm, ArgsView args) // [](VM *vm, ArgsView args)
// { // {
@ -160,7 +184,12 @@ namespace pkpy
void PyDeque::_gc_mark() const 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) std::stringstream PyDeque::getRepr(VM *vm)
{ {
@ -178,6 +207,37 @@ namespace pkpy
return ss; 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() void PyDeque::reverse()
{ {
this->dequeItems->reverse(); this->dequeItems->reverse();
@ -216,7 +276,15 @@ namespace pkpy
int PyDeque::count(VM *vm, PyObject *obj) 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() void PyDeque::clear()
{ {