mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-22 20:40:18 +00:00
...
This commit is contained in:
parent
19b2eda72a
commit
8d3bb6faa5
@ -144,6 +144,9 @@ public:
|
||||
PyObject* _last_exception; // last exception
|
||||
PyObject* _curr_class; // current class being defined
|
||||
|
||||
// this is for repr() recursion detection (no need to mark)
|
||||
std::set<PyObject*> _repr_recursion_set;
|
||||
|
||||
// cached code objects for FSTRING_EVAL
|
||||
std::map<std::string_view, CodeObject_> _cached_codes;
|
||||
|
||||
|
@ -57,7 +57,6 @@ 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::string 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,80 +73,76 @@ namespace pkpy
|
||||
});
|
||||
// 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",
|
||||
[](VM *vm, ArgsView args)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
||||
int index = CAST(int, args[1]);
|
||||
index = vm->normalized_index(index, self.dequeItems.size()); // error is handled by the vm->normalized_index
|
||||
return self.dequeItems.at(index);
|
||||
});
|
||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0, PyObject* _1)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque &, _0);
|
||||
int index = CAST(int, _1);
|
||||
index = vm->normalized_index(index, self.dequeItems.size()); // error is handled by the vm->normalized_index
|
||||
return self.dequeItems.at(index);
|
||||
});
|
||||
// sets 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, "__setitem__(self, index, newValue) -> None",
|
||||
[](VM *vm, ArgsView args)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
||||
int index = CAST(int, args[1]);
|
||||
PyObject *newValue = args[2];
|
||||
index = vm->normalized_index(index, self.dequeItems.size()); // error is handled by the vm->normalized_index
|
||||
self.dequeItems.at(index) = newValue;
|
||||
return vm->None;
|
||||
});
|
||||
vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0, PyObject* _1, PyObject* _2)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque&, _0);
|
||||
int index = CAST(int, _1);
|
||||
index = vm->normalized_index(index, self.dequeItems.size()); // error is handled by the vm->normalized_index
|
||||
self.dequeItems.at(index) = _2;
|
||||
});
|
||||
// erases 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, "__delitem__(self, index) -> None",
|
||||
[](VM *vm, ArgsView args)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
||||
int index = CAST(int, args[1]);
|
||||
index = vm->normalized_index(index, self.dequeItems.size()); // error is handled by the vm->normalized_index
|
||||
self.dequeItems.erase(self.dequeItems.begin() + index);
|
||||
return vm->None;
|
||||
});
|
||||
// returns the length of the deque
|
||||
vm->bind(type, "__len__(self) -> int",
|
||||
[](VM *vm, ArgsView args)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
||||
return VAR(self.dequeItems.size());
|
||||
});
|
||||
// returns an iterator for the deque
|
||||
vm->bind(type, "__iter__(self) -> deque_iterator",
|
||||
[](VM *vm, ArgsView args)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
||||
return vm->heap.gcnew<PyDequeIter>(
|
||||
PyDequeIter::_type(vm), args[0],
|
||||
self.dequeItems.begin(), self.dequeItems.end());
|
||||
});
|
||||
// returns a string representation of the deque
|
||||
vm->bind(type, "__repr__(self) -> str",
|
||||
[](VM *vm, ArgsView args)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
||||
return VAR(self.getRepr(vm, args[0]));
|
||||
});
|
||||
// returns a string representation of the deque
|
||||
vm->bind(type, "__str__(self) -> str",
|
||||
[](VM *vm, ArgsView args)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
||||
return VAR(self.getRepr(vm, args[0]));
|
||||
});
|
||||
vm->bind__delitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0, PyObject* _1)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque&, _0);
|
||||
int index = CAST(int, _1);
|
||||
index = vm->normalized_index(index, self.dequeItems.size()); // error is handled by the vm->normalized_index
|
||||
self.dequeItems.erase(self.dequeItems.begin() + index);
|
||||
});
|
||||
|
||||
vm->bind__len__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque&, _0);
|
||||
return (i64)self.dequeItems.size();
|
||||
});
|
||||
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque &, _0);
|
||||
return vm->heap.gcnew<PyDequeIter>(
|
||||
PyDequeIter::_type(vm), _0,
|
||||
self.dequeItems.begin(), self.dequeItems.end());
|
||||
});
|
||||
|
||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0)
|
||||
{
|
||||
if(vm->_repr_recursion_set.count(_0)) return VAR("[...]");
|
||||
const PyDeque &self = _CAST(PyDeque&, _0);
|
||||
SStream ss;
|
||||
ss << "deque([";
|
||||
vm->_repr_recursion_set.insert(_0);
|
||||
for (auto it = self.dequeItems.begin(); it != self.dequeItems.end(); ++it)
|
||||
{
|
||||
ss << CAST(Str&, vm->py_repr(*it));
|
||||
if (it != self.dequeItems.end() - 1) ss << ", ";
|
||||
}
|
||||
vm->_repr_recursion_set.erase(_0);
|
||||
self.bounded ? ss << "], maxlen=" << self.maxlen << ")" : ss << "])";
|
||||
return VAR(ss.str());
|
||||
});
|
||||
|
||||
// enables comparison between two deques, == and != are supported
|
||||
vm->bind(type, "__eq__(self, other) -> bool",
|
||||
[](VM *vm, ArgsView args)
|
||||
{
|
||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
||||
PyDeque &other = _CAST(PyDeque &, args[1]);
|
||||
if (self.dequeItems.size() != other.dequeItems.size()) // trivial case
|
||||
return VAR(false);
|
||||
for (int i = 0; i < self.dequeItems.size(); i++)
|
||||
if (!vm->py_eq(self.dequeItems[i], other.dequeItems[i]))
|
||||
return VAR(false);
|
||||
return VAR(true);
|
||||
});
|
||||
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0, PyObject* _1)
|
||||
{
|
||||
const PyDeque &self = _CAST(PyDeque&, _0);
|
||||
if(!is_non_tagged_type(_0, PyDeque::_type(vm))) return vm->NotImplemented;
|
||||
const PyDeque &other = _CAST(PyDeque&, _1);
|
||||
if (self.dequeItems.size() != other.dequeItems.size()) return vm->False;
|
||||
for (int i = 0; i < self.dequeItems.size(); i++){
|
||||
if (vm->py_ne(self.dequeItems[i], other.dequeItems[i])) return vm->False;
|
||||
}
|
||||
return vm->True;
|
||||
});
|
||||
|
||||
// clear the deque
|
||||
vm->bind(type, "clear(self) -> None",
|
||||
[](VM *vm, ArgsView args)
|
||||
@ -426,22 +421,6 @@ namespace pkpy
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string 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.str();
|
||||
}
|
||||
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
|
||||
|
@ -659,17 +659,16 @@ void init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
_vm->bind__repr__(VM::tp_list, [](VM* vm, PyObject* _0){
|
||||
if(vm->_repr_recursion_set.count(_0)) return VAR("[...]");
|
||||
List& iterable = _CAST(List&, _0);
|
||||
SStream ss;
|
||||
ss << '[';
|
||||
vm->_repr_recursion_set.insert(_0);
|
||||
for(int i=0; i<iterable.size(); i++){
|
||||
if(iterable[i] == _0){
|
||||
ss << "[...]";
|
||||
}else{
|
||||
ss << CAST(Str&, vm->py_repr(iterable[i]));
|
||||
}
|
||||
ss << CAST(Str&, vm->py_repr(iterable[i]));
|
||||
if(i != iterable.size()-1) ss << ", ";
|
||||
}
|
||||
vm->_repr_recursion_set.erase(_0);
|
||||
ss << ']';
|
||||
return VAR(ss.str());
|
||||
});
|
||||
@ -1080,16 +1079,19 @@ void init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
_vm->bind__repr__(VM::tp_mappingproxy, [](VM* vm, PyObject* _0) {
|
||||
if(vm->_repr_recursion_set.count(_0)) return VAR("{...}");
|
||||
MappingProxy& self = _CAST(MappingProxy&, _0);
|
||||
SStream ss;
|
||||
ss << "mappingproxy({";
|
||||
bool first = true;
|
||||
vm->_repr_recursion_set.insert(_0);
|
||||
for(auto& item : self.attr().items()){
|
||||
if(!first) ss << ", ";
|
||||
first = false;
|
||||
ss << item.first.escape() << ": ";
|
||||
ss << CAST(Str, vm->py_repr(item.second));
|
||||
}
|
||||
vm->_repr_recursion_set.erase(_0);
|
||||
ss << "})";
|
||||
return VAR(ss.str());
|
||||
});
|
||||
@ -1227,20 +1229,18 @@ void init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
_vm->bind__repr__(VM::tp_dict, [](VM* vm, PyObject* _0) {
|
||||
if(vm->_repr_recursion_set.count(_0)) return VAR("{...}");
|
||||
Dict& self = _CAST(Dict&, _0);
|
||||
SStream ss;
|
||||
ss << "{";
|
||||
bool first = true;
|
||||
vm->_repr_recursion_set.insert(_0);
|
||||
self.apply([&](PyObject* k, PyObject* v){
|
||||
if(!first) ss << ", ";
|
||||
first = false;
|
||||
ss << CAST(Str&, vm->py_repr(k)) << ": ";
|
||||
if(v == _0){
|
||||
ss << "{...}";
|
||||
}else{
|
||||
ss << CAST(Str&, vm->py_repr(v));
|
||||
}
|
||||
ss << CAST(Str&, vm->py_repr(k)) << ": " << CAST(Str&, vm->py_repr(v));
|
||||
});
|
||||
vm->_repr_recursion_set.erase(_0);
|
||||
ss << "}";
|
||||
return VAR(ss.str());
|
||||
});
|
||||
|
@ -97,7 +97,7 @@ assert b[
|
||||
0] == 1
|
||||
|
||||
a = []
|
||||
a.append(1)
|
||||
a.append(a)
|
||||
a.append(0)
|
||||
a.append([1, 2, a])
|
||||
|
||||
assert repr(a) == '[1, [...]]'
|
||||
assert repr(a) == "[0, [1, 2, [...]]]"
|
||||
|
Loading…
x
Reference in New Issue
Block a user