mirror of
https://github.com/pocketpy/pocketpy
synced 2025-11-09 21:20:17 +00:00
Cleaned up and added __str__() support
This commit is contained in:
parent
a5a18154f4
commit
385e9492c8
@ -1,19 +1,13 @@
|
||||
#include "pocketpy/collections.h"
|
||||
namespace pkpy
|
||||
{
|
||||
struct PyDequeIter
|
||||
struct PyDequeIter // Iterator for the deque type
|
||||
{
|
||||
// Iterator for the deque type
|
||||
PY_CLASS(PyDequeIter, builtins, "_deque_iterator")
|
||||
PyObject *ref;
|
||||
bool is_reversed;
|
||||
std::deque<PyObject *>::iterator begin;
|
||||
std::deque<PyObject *>::iterator end;
|
||||
std::deque<PyObject *>::iterator current;
|
||||
std::deque<PyObject *>::reverse_iterator rbegin;
|
||||
std::deque<PyObject *>::reverse_iterator rend;
|
||||
std::deque<PyObject *>::reverse_iterator rcurrent;
|
||||
|
||||
std::deque<PyObject *>::iterator begin, end, current;
|
||||
std::deque<PyObject *>::reverse_iterator rbegin, rend, rcurrent;
|
||||
PyDequeIter(PyObject *ref, std::deque<PyObject *>::iterator begin, std::deque<PyObject *>::iterator end)
|
||||
: ref(ref), begin(begin), end(end), current(begin)
|
||||
{
|
||||
@ -24,7 +18,6 @@ namespace pkpy
|
||||
{
|
||||
this->is_reversed = true;
|
||||
}
|
||||
|
||||
void _gc_mark() const { PK_OBJ_MARK(ref); }
|
||||
static void _register(VM *vm, PyObject *mod, PyObject *type);
|
||||
};
|
||||
@ -52,7 +45,6 @@ namespace pkpy
|
||||
return ret;
|
||||
} });
|
||||
}
|
||||
// STARTING HERE
|
||||
struct PyDeque
|
||||
{
|
||||
PY_CLASS(PyDeque, collections, deque);
|
||||
@ -64,7 +56,7 @@ namespace pkpy
|
||||
void insertObj(bool front, bool back, int index, PyObject *item); // insert at index, used purely for internal purposes: append, appendleft, insert methods
|
||||
PyObject *popObj(bool front, bool back, PyObject *item, VM *vm); // pop at index, used purely for internal purposes: pop, popleft, remove methods
|
||||
int findIndex(VM *vm, PyObject *obj, int start, int stop); // find the index of the given object in the deque
|
||||
std::stringstream getRepr(VM *vm); // get the string representation of the deque
|
||||
std::stringstream getRepr(VM *vm, PyObject* thisObj); // get the string representation of the deque
|
||||
// Special methods
|
||||
static void _register(VM *vm, PyObject *mod, PyObject *type); // register the type
|
||||
void _gc_mark() const; // needed for container types, mark all objects in the deque for gc
|
||||
@ -74,50 +66,11 @@ namespace pkpy
|
||||
vm->bind(type, "__new__(cls, iterable=None, maxlen=None)",
|
||||
[](VM *vm, ArgsView args)
|
||||
{
|
||||
// printf("NEW CALLED!!\n");
|
||||
Type cls_t = PK_OBJ_GET(Type, args[0]);
|
||||
PyObject *iterable = args[1];
|
||||
PyObject *maxlen = args[2];
|
||||
return vm->heap.gcnew<PyDeque>(cls_t, vm, iterable, maxlen);
|
||||
});
|
||||
// vm->bind(type, "__init__(self, iterable=None, maxlen=None)",
|
||||
// [](VM *vm, ArgsView args)
|
||||
// {
|
||||
// // printf("INIT CALLED!!\n");
|
||||
// PyDeque &self = _CAST(PyDeque &, args[0]);
|
||||
// PyObject *iterable = args[1];
|
||||
// PyObject *maxlen = args[2];
|
||||
|
||||
// if (!vm->py_equals(maxlen, vm->None)) // fix the maxlen first
|
||||
// {
|
||||
// int tmp = CAST(int, maxlen);
|
||||
// if (tmp < 0)
|
||||
// vm->ValueError("maxlen must be non-negative");
|
||||
// else
|
||||
// {
|
||||
// self.maxlen = tmp;
|
||||
// self.bounded = true;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// self.bounded = false;
|
||||
// self.maxlen = -1;
|
||||
// }
|
||||
// if (!vm->py_equals(iterable, vm->None))
|
||||
// {
|
||||
// self.dequeItems.clear(); // clear the deque
|
||||
// auto _lock = vm->heap.gc_scope_lock(); // locking the heap
|
||||
// PyObject *it = vm->py_iter(args[1]); // strong ref
|
||||
// PyObject *obj = vm->py_next(it);
|
||||
// while (obj != vm->StopIteration)
|
||||
// {
|
||||
// self.insertObj(false, true, -1, obj);
|
||||
// obj = vm->py_next(it);
|
||||
// }
|
||||
// }
|
||||
// return args[0];
|
||||
// });
|
||||
// gets the item at the given index, if index is negative, it will be treated as index + len(deque)
|
||||
// if the index is out of range, IndexError will be thrown --> required for [] operator
|
||||
vm->bind(type, "__getitem__(self, index) -> PyObject",
|
||||
@ -172,18 +125,15 @@ namespace pkpy
|
||||
[](VM *vm, ArgsView args)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
||||
std::stringstream ss;
|
||||
ss << "deque([";
|
||||
for (auto it = self.dequeItems.begin(); it != self.dequeItems.end(); ++it)
|
||||
{
|
||||
if (*it == args[0])
|
||||
ss << "[...]";
|
||||
else
|
||||
ss << CAST(Str &, vm->py_repr(*it));
|
||||
if (it != self.dequeItems.end() - 1)
|
||||
ss << ", ";
|
||||
}
|
||||
self.bounded ? ss << "], maxlen=" << self.maxlen << ")" : ss << "])";
|
||||
std::stringstream ss = self.getRepr(vm, args[0]);
|
||||
return VAR(ss.str());
|
||||
});
|
||||
// returns a string representation of the deque
|
||||
vm->bind(type, "__str__(self) -> str",
|
||||
[](VM *vm, ArgsView args)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
||||
std::stringstream ss = self.getRepr(vm, args[0]);
|
||||
return VAR(ss.str());
|
||||
});
|
||||
// enables comparison between two deques, == and != are supported
|
||||
@ -287,8 +237,8 @@ namespace pkpy
|
||||
{
|
||||
if (vm->py_equals((*it), obj))
|
||||
cnt++;
|
||||
if (sz != self.dequeItems.size()) // mutating the deque during iteration is not allowed
|
||||
vm->RuntimeError("deque mutated during iteration"); // TODO replace this with RuntimeError
|
||||
if (sz != self.dequeItems.size())// mutating the deque during iteration is not allowed
|
||||
vm->RuntimeError("deque mutated during iteration");
|
||||
}
|
||||
return VAR(cnt);
|
||||
});
|
||||
@ -477,7 +427,22 @@ namespace pkpy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::stringstream PyDeque::getRepr(VM *vm, PyObject *thisObj)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "deque([";
|
||||
for (auto it = this->dequeItems.begin(); it != this->dequeItems.end(); ++it)
|
||||
{
|
||||
if (*it == thisObj)
|
||||
ss << "[...]";
|
||||
else
|
||||
ss << CAST(Str &, vm->py_repr(*it));
|
||||
if (it != this->dequeItems.end() - 1)
|
||||
ss << ", ";
|
||||
}
|
||||
this->bounded ? ss << "], maxlen=" << this->maxlen << ")" : ss << "])";
|
||||
return ss;
|
||||
}
|
||||
int PyDeque::findIndex(VM *vm, PyObject *obj, int start, int stop)
|
||||
{
|
||||
// the following code is special purpose normalization for this method, taken from CPython: _collectionsmodule.c file
|
||||
@ -504,8 +469,8 @@ namespace pkpy
|
||||
{
|
||||
if (vm->py_equals(this->dequeItems[i], obj))
|
||||
return i;
|
||||
if (sz != this->dequeItems.size()) // mutating the deque during iteration is not allowed
|
||||
vm->RuntimeError("deque mutated during iteration"); // TODO replace this with RuntimeError
|
||||
if (sz != this->dequeItems.size())// mutating the deque during iteration is not allowed
|
||||
vm->RuntimeError("deque mutated during iteration");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -23,16 +23,10 @@ assert q == deque([1, 2])
|
||||
|
||||
def assertEqual(a, b):
|
||||
assert a == b
|
||||
|
||||
|
||||
def assertNotEqual(a, b):
|
||||
assert a != b
|
||||
|
||||
|
||||
def assertRaises(callable, *args, **kwargs):
|
||||
callable(*args, **kwargs)
|
||||
print("X Failed Tests for {} for args: {} {}".format(
|
||||
str(callable), str(args), str(kwargs)))
|
||||
def printFailed(function_name, *args, **kwargs):
|
||||
print("X Failed Tests for {} for args: {} {}".format(str(function_name), str(args), str(kwargs)))
|
||||
|
||||
|
||||
BIG = 100000
|
||||
@ -67,12 +61,16 @@ assertEqual(list(d), list(range(50, 150)))
|
||||
try:
|
||||
dq = deque()
|
||||
dq.maxlen = -1
|
||||
printFailed("deque.maxlen", -1)
|
||||
exit(1)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
dq = deque()
|
||||
dq.maxlen = -2
|
||||
printFailed("deque.maxlen", -2)
|
||||
exit(1)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
@ -122,7 +120,7 @@ assertEqual(deque('abc', maxlen=0).maxlen, 0)
|
||||
try:
|
||||
d = deque('abc')
|
||||
d.maxlen = 10
|
||||
print("X Failed Tests!!")
|
||||
printFailed("deque.maxlen", 10)
|
||||
exit(1)
|
||||
except AttributeError:
|
||||
pass
|
||||
@ -135,14 +133,14 @@ for s in ('', 'abracadabra', 'simsalabim'*500+'abc'):
|
||||
assertEqual(s.count(letter), d.count(letter))
|
||||
try:
|
||||
d.count()
|
||||
print("X Failed Tests!!")
|
||||
printFailed("deque.count")
|
||||
exit(1)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
d.count(1, 2)
|
||||
print("X Failed Tests!!")
|
||||
printFailed("deque.count", 1, 2)
|
||||
exit(1)
|
||||
except TypeError:
|
||||
pass
|
||||
@ -157,7 +155,7 @@ d = deque([1, 2, BadCompare(), 3])
|
||||
|
||||
try:
|
||||
d.count(2)
|
||||
print("X Failed Tests!!")
|
||||
printFailed("deque.count", 2)
|
||||
exit(1)
|
||||
except ArithmeticError:
|
||||
pass
|
||||
@ -165,7 +163,7 @@ except ArithmeticError:
|
||||
d = deque([1, 2, 3])
|
||||
try:
|
||||
d.count(BadCompare())
|
||||
print("X Failed Tests!!")
|
||||
printFailed("deque.count", "BadCompare()")
|
||||
exit(1)
|
||||
except ArithmeticError:
|
||||
pass
|
||||
@ -183,7 +181,7 @@ m.d = d
|
||||
|
||||
try:
|
||||
d.count(3)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.count", "MutatingCompare()")
|
||||
exit(1)
|
||||
except RuntimeError:
|
||||
pass
|
||||
@ -239,7 +237,7 @@ d = deque(range(n))
|
||||
d[n//2] = MutateCmp(d, False)
|
||||
try:
|
||||
n in d
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.__contains__", n)
|
||||
exit(1)
|
||||
except RuntimeError:
|
||||
pass
|
||||
@ -255,7 +253,7 @@ d = deque(range(n))
|
||||
d[n//2] = BadCmp()
|
||||
try:
|
||||
n in d
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.__contains__", n)
|
||||
exit(1)
|
||||
except RuntimeError:
|
||||
pass
|
||||
@ -273,7 +271,7 @@ d = deque([A(), A()])
|
||||
|
||||
try:
|
||||
_ = 3 in d
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.__contains__", 3)
|
||||
exit(1)
|
||||
except RuntimeError:
|
||||
pass
|
||||
@ -281,7 +279,7 @@ except RuntimeError:
|
||||
d = deque([A(), A()])
|
||||
try:
|
||||
_ = d.count(3)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.count", 3)
|
||||
exit(1)
|
||||
except RuntimeError:
|
||||
pass
|
||||
@ -293,7 +291,7 @@ except RuntimeError:
|
||||
d = deque('a')
|
||||
try:
|
||||
d.extend(1)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.extend", 1)
|
||||
exit(1)
|
||||
except TypeError:
|
||||
pass
|
||||
@ -307,7 +305,7 @@ assertEqual(list(d), list('abcdabcd'))
|
||||
d = deque('a')
|
||||
try:
|
||||
d.extendleft(1)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.extendleft", 1)
|
||||
exit(1)
|
||||
except TypeError:
|
||||
pass
|
||||
@ -320,7 +318,7 @@ d.extendleft(range(1000))
|
||||
assertEqual(list(d), list(reversed(range(1000))))
|
||||
try:
|
||||
d.extendleft(fail())
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.extendleft", fail())
|
||||
exit(1)
|
||||
except SyntaxError:
|
||||
pass
|
||||
@ -345,13 +343,13 @@ assertEqual(d[-1], 'n')
|
||||
d = deque()
|
||||
try:
|
||||
d.__getitem__(0)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.__getitem__", 0)
|
||||
exit(1)
|
||||
except IndexError:
|
||||
pass
|
||||
try:
|
||||
d.__getitem__(-1)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.__getitem__", -1)
|
||||
exit(1)
|
||||
except IndexError:
|
||||
pass
|
||||
@ -366,7 +364,7 @@ for n in 1, 2, 30, 40, 200:
|
||||
|
||||
try:
|
||||
d.index(n+1)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.index", n+1)
|
||||
exit(1)
|
||||
except ValueError:
|
||||
pass
|
||||
@ -377,7 +375,7 @@ for n in 1, 2, 30, 40, 200:
|
||||
|
||||
try:
|
||||
d.index(n)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.index", n)
|
||||
exit(1)
|
||||
except RuntimeError:
|
||||
pass
|
||||
@ -388,7 +386,7 @@ for n in 1, 2, 30, 40, 200:
|
||||
|
||||
try:
|
||||
d.index(n)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.index", n)
|
||||
exit(1)
|
||||
except RuntimeError:
|
||||
pass
|
||||
@ -430,7 +428,7 @@ for step in range(100):
|
||||
d = deque('A' * 3)
|
||||
try:
|
||||
d.index('A', 1, 0)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.index", 'A', 1, 0)
|
||||
exit(1)
|
||||
except ValueError:
|
||||
pass
|
||||
@ -451,7 +449,7 @@ data = 'ABC'
|
||||
d = deque(data, maxlen=len(data))
|
||||
try:
|
||||
d.insert(0, 'Z')
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.insert", 0, 'Z')
|
||||
exit(1)
|
||||
except IndexError:
|
||||
pass
|
||||
@ -484,14 +482,14 @@ n = 500 # O(n**2) test, don't make this too big
|
||||
d = deque(range(n))
|
||||
try:
|
||||
d.__delitem__(-n-1)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.__delitem__", -n-1)
|
||||
exit(1)
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
try:
|
||||
d.__delitem__(n)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.__delitem__", n)
|
||||
exit(1)
|
||||
except IndexError:
|
||||
pass
|
||||
@ -518,7 +516,7 @@ for i in range(n):
|
||||
assertEqual(list(d), data[:i])
|
||||
try:
|
||||
d.reverse(1)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.reverse", 1)
|
||||
exit(1)
|
||||
except TypeError:
|
||||
pass
|
||||
@ -570,14 +568,14 @@ for i in range(BIG+17):
|
||||
assertEqual(tuple(d), tuple(e))
|
||||
try:
|
||||
d.rotate(1, 2)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.rotate", 1, 2)
|
||||
exit(1)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
d.rotate(1, 10)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.rotate", 1, 10)
|
||||
exit(1)
|
||||
except TypeError:
|
||||
pass
|
||||
@ -596,7 +594,7 @@ d.pop()
|
||||
assertEqual(len(d), 0)
|
||||
try:
|
||||
d.pop()
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.pop")
|
||||
exit(1)
|
||||
except IndexError:
|
||||
pass
|
||||
@ -613,13 +611,13 @@ assertEqual(len(d), 0)
|
||||
d = deque()
|
||||
try:
|
||||
d.pop()
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.pop")
|
||||
exit(1)
|
||||
except IndexError:
|
||||
pass
|
||||
try:
|
||||
d.popleft()
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.popleft")
|
||||
exit(1)
|
||||
except IndexError:
|
||||
pass
|
||||
@ -642,7 +640,7 @@ d.remove('c')
|
||||
assertEqual(d, deque('abdefghij'))
|
||||
try:
|
||||
d.remove('c')
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.remove", "c")
|
||||
exit(1)
|
||||
except ValueError:
|
||||
pass
|
||||
@ -654,7 +652,7 @@ e = deque(d)
|
||||
|
||||
try:
|
||||
d.remove('c')
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.remove", "c")
|
||||
exit(1)
|
||||
except RuntimeError:
|
||||
pass
|
||||
@ -668,7 +666,7 @@ for match in (True, False):
|
||||
d.extend([MutateCmp(d, match), 'c'])
|
||||
try:
|
||||
d.remove('c')
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque.remove", "c")
|
||||
exit(1)
|
||||
except IndexError:
|
||||
pass
|
||||
@ -687,13 +685,13 @@ assertEqual(repr(d)[-20:], '7, 198, 199, [...]])')
|
||||
|
||||
try:
|
||||
deque('abc', 2, 3)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque", 'abc', 2, 3)
|
||||
exit(1)
|
||||
except TypeError:
|
||||
pass
|
||||
try:
|
||||
deque(1)
|
||||
print("X Failed Tests!")
|
||||
printFailed("deque", 1)
|
||||
exit(1)
|
||||
except TypeError:
|
||||
pass
|
||||
@ -701,7 +699,7 @@ except TypeError:
|
||||
|
||||
######### test hash #############
|
||||
try:
|
||||
assertRaises(hash, deque('abc'))
|
||||
hash(deque('abcd'))
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user