WIP: added more functionalities

This commit is contained in:
S. Mahmudul Hasan 2023-10-14 13:15:39 -04:00
parent 2852c1ab7e
commit ff5e1a8de2
2 changed files with 100 additions and 175 deletions

View File

@ -10,157 +10,25 @@
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;
// }
// ~DequeNode()
// {
// }
// };
// 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()
// {
// 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++;
// }
// 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;
// }
// 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;
// }
// 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;
// }
// // swap the head and tail pointers
// DequeNode *tmp = this->head;
// this->head = this->tail;
// this->tail = tmp;
// }
// };
// STARTING HERE
struct PyDeque
{
PY_CLASS(PyDeque, mycollections, deque);
// some fields can be defined here
std::deque<PyObject*>dequeItems;
void appendLeft(PyObject *item);
void append(PyObject *item);
PyObject *popLeft();
PyObject *pop();
bool insert(int index, PyObject *item);
bool remove(VM *vm, PyObject *item);
void rotate(int n);
std::stringstream getRepr(VM *vm);
void reverse();
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();

View File

@ -55,17 +55,14 @@ namespace pkpy
vm->bind(type, "copy(self) -> deque",
[](VM *vm, ArgsView args)
{
//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>(PyDeque::_type(vm), *newDeque);
//TODO: STILL MEMORY LEAKING??
PyDeque &self = _CAST(PyDeque &, args[0]);
PyDeque *newDeque = new PyDeque();
for (auto it = self.dequeItems.begin(); it != self.dequeItems.end(); ++it)
{
newDeque->append(*it);
}
return vm->heap.gcnew<PyDeque>(PyDeque::_type(vm), *newDeque);
});
vm->bind(type, "count(self, obj) -> int",
@ -126,9 +123,13 @@ namespace pkpy
vm->bind(type, "insert(self, index, obj) -> None",
[](VM *vm, ArgsView args)
{
// TODO: implement and validate
PyDeque &self = _CAST(PyDeque &, args[0]);
int index = CAST(int, args[1]);
PyObject *obj = args[2];
printf("TODO: implement deque.insert()");
//TODO: HANDLE MAX SIZE CASE LATER -> Throw IndexError
self.insert(index, obj);
return vm->None;
});
@ -157,8 +158,13 @@ namespace pkpy
vm->bind(type, "remove(self, obj) -> None",
[](VM *vm, ArgsView args)
{
// TODO: implement and validate
printf("TODO: implement deque.index()");
PyDeque &self = _CAST(PyDeque &, args[0]);
PyObject *obj = args[1];
bool removed = self.remove(vm, obj);
if(!removed)
vm->ValueError(_CAST(Str &, vm->py_repr(obj)) + " is not in list");
return vm->None;
});
@ -169,11 +175,14 @@ namespace pkpy
self.reverse();
return vm->None;
});
vm->bind(type, "rotate(self, n=1) -> None",
[](VM *vm, ArgsView args)
{
// TODO: implement and validate
printf("TODO: implement deque.rotate()");
PyDeque &self = _CAST(PyDeque &, args[0]);
int n = CAST(int, args[1]);
self.rotate(n);
return vm->None;
});
@ -184,11 +193,60 @@ namespace pkpy
// });
}
void PyDeque::_gc_mark() const
void PyDeque::rotate(int n)
{
//TODO: HOW TO IMPLEMENT THIS?
int direction = n > 0 ? 1 : -1;
int sz = this->dequeItems.size();
n = abs(n);
n = n % sz; // make sure n is in range
for (int i = 0; i < n; i++)
{
if (direction == 1)
{
PyObject *tmp = this->dequeItems.back();
this->dequeItems.pop_back();
this->dequeItems.push_front(tmp);
}
else
{
PyObject *tmp = this->dequeItems.front();
this->dequeItems.pop_front();
this->dequeItems.push_back(tmp);
}
}
}
bool PyDeque::remove(VM *vm, PyObject *item)
{
for (auto it = this->dequeItems.begin(); it != this->dequeItems.end(); ++it)
{
if (vm->py_equals((*it), item))
{
this->dequeItems.erase(it);
return true;
}
}
return false;
}
bool PyDeque::insert(int index, PyObject *item)
{
if (index < 0)
this->dequeItems.appendLeft(item);
else if(index >= this->dequeItems.size())
this->dequeItems.append(item);
else
this->dequeItems.insert((this->dequeItems.begin() + index), item);
return true;
}
void PyDeque::_gc_mark() const
{
// TODO: HOW TO IMPLEMENT THIS?
}
std::stringstream PyDeque::getRepr(VM *vm)
{
@ -221,7 +279,7 @@ namespace pkpy
}
int dequeSize = this->dequeItems.size();
for (int i = startPos; i<dequeSize && i < endPos; i++)
for (int i = startPos; i < dequeSize && i < endPos; i++)
{
if (vm->py_equals(this->dequeItems[i], obj))
{
@ -231,7 +289,6 @@ namespace pkpy
return -1;
}
void PyDeque::reverse()
{
int sz = this->dequeItems.size();