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* _last_exception; // last exception
|
||||||
PyObject* _curr_class; // current class being defined
|
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
|
// cached code objects for FSTRING_EVAL
|
||||||
std::map<std::string_view, CodeObject_> _cached_codes;
|
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
|
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
|
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
|
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
|
// Special methods
|
||||||
static void _register(VM *vm, PyObject *mod, PyObject *type); // register the type
|
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
|
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)
|
// 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
|
// if the index is out of range, IndexError will be thrown --> required for [] operator
|
||||||
vm->bind(type, "__getitem__(self, index) -> PyObject",
|
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0, PyObject* _1)
|
||||||
[](VM *vm, ArgsView args)
|
{
|
||||||
{
|
PyDeque &self = _CAST(PyDeque &, _0);
|
||||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
int index = CAST(int, _1);
|
||||||
int index = CAST(int, args[1]);
|
index = vm->normalized_index(index, self.dequeItems.size()); // error is handled by the vm->normalized_index
|
||||||
index = vm->normalized_index(index, self.dequeItems.size()); // error is handled by the vm->normalized_index
|
return self.dequeItems.at(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)
|
// 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
|
// if the index is out of range, IndexError will be thrown --> required for [] operator
|
||||||
vm->bind(type, "__setitem__(self, index, newValue) -> None",
|
vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0, PyObject* _1, PyObject* _2)
|
||||||
[](VM *vm, ArgsView args)
|
{
|
||||||
{
|
PyDeque &self = _CAST(PyDeque&, _0);
|
||||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
int index = CAST(int, _1);
|
||||||
int index = CAST(int, args[1]);
|
index = vm->normalized_index(index, self.dequeItems.size()); // error is handled by the vm->normalized_index
|
||||||
PyObject *newValue = args[2];
|
self.dequeItems.at(index) = _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;
|
|
||||||
});
|
|
||||||
// erases the item at the given index, if index is negative, it will be treated as index + len(deque)
|
// 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
|
// if the index is out of range, IndexError will be thrown --> required for [] operator
|
||||||
vm->bind(type, "__delitem__(self, index) -> None",
|
vm->bind__delitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0, PyObject* _1)
|
||||||
[](VM *vm, ArgsView args)
|
{
|
||||||
{
|
PyDeque &self = _CAST(PyDeque&, _0);
|
||||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
int index = CAST(int, _1);
|
||||||
int index = CAST(int, args[1]);
|
index = vm->normalized_index(index, self.dequeItems.size()); // error is handled by the vm->normalized_index
|
||||||
index = vm->normalized_index(index, self.dequeItems.size()); // error is handled by the vm->normalized_index
|
self.dequeItems.erase(self.dequeItems.begin() + index);
|
||||||
self.dequeItems.erase(self.dequeItems.begin() + index);
|
});
|
||||||
return vm->None;
|
|
||||||
});
|
vm->bind__len__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0)
|
||||||
// returns the length of the deque
|
{
|
||||||
vm->bind(type, "__len__(self) -> int",
|
PyDeque &self = _CAST(PyDeque&, _0);
|
||||||
[](VM *vm, ArgsView args)
|
return (i64)self.dequeItems.size();
|
||||||
{
|
});
|
||||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
|
||||||
return VAR(self.dequeItems.size());
|
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0)
|
||||||
});
|
{
|
||||||
// returns an iterator for the deque
|
PyDeque &self = _CAST(PyDeque &, _0);
|
||||||
vm->bind(type, "__iter__(self) -> deque_iterator",
|
return vm->heap.gcnew<PyDequeIter>(
|
||||||
[](VM *vm, ArgsView args)
|
PyDequeIter::_type(vm), _0,
|
||||||
{
|
self.dequeItems.begin(), self.dequeItems.end());
|
||||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
});
|
||||||
return vm->heap.gcnew<PyDequeIter>(
|
|
||||||
PyDequeIter::_type(vm), args[0],
|
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0)
|
||||||
self.dequeItems.begin(), self.dequeItems.end());
|
{
|
||||||
});
|
if(vm->_repr_recursion_set.count(_0)) return VAR("[...]");
|
||||||
// returns a string representation of the deque
|
const PyDeque &self = _CAST(PyDeque&, _0);
|
||||||
vm->bind(type, "__repr__(self) -> str",
|
SStream ss;
|
||||||
[](VM *vm, ArgsView args)
|
ss << "deque([";
|
||||||
{
|
vm->_repr_recursion_set.insert(_0);
|
||||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
for (auto it = self.dequeItems.begin(); it != self.dequeItems.end(); ++it)
|
||||||
return VAR(self.getRepr(vm, args[0]));
|
{
|
||||||
});
|
ss << CAST(Str&, vm->py_repr(*it));
|
||||||
// returns a string representation of the deque
|
if (it != self.dequeItems.end() - 1) ss << ", ";
|
||||||
vm->bind(type, "__str__(self) -> str",
|
}
|
||||||
[](VM *vm, ArgsView args)
|
vm->_repr_recursion_set.erase(_0);
|
||||||
{
|
self.bounded ? ss << "], maxlen=" << self.maxlen << ")" : ss << "])";
|
||||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
return VAR(ss.str());
|
||||||
return VAR(self.getRepr(vm, args[0]));
|
});
|
||||||
});
|
|
||||||
// enables comparison between two deques, == and != are supported
|
// enables comparison between two deques, == and != are supported
|
||||||
vm->bind(type, "__eq__(self, other) -> bool",
|
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0, PyObject* _1)
|
||||||
[](VM *vm, ArgsView args)
|
{
|
||||||
{
|
const PyDeque &self = _CAST(PyDeque&, _0);
|
||||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
if(!is_non_tagged_type(_0, PyDeque::_type(vm))) return vm->NotImplemented;
|
||||||
PyDeque &other = _CAST(PyDeque &, args[1]);
|
const PyDeque &other = _CAST(PyDeque&, _1);
|
||||||
if (self.dequeItems.size() != other.dequeItems.size()) // trivial case
|
if (self.dequeItems.size() != other.dequeItems.size()) return vm->False;
|
||||||
return VAR(false);
|
for (int i = 0; i < self.dequeItems.size(); i++){
|
||||||
for (int i = 0; i < self.dequeItems.size(); i++)
|
if (vm->py_ne(self.dequeItems[i], other.dequeItems[i])) return vm->False;
|
||||||
if (!vm->py_eq(self.dequeItems[i], other.dequeItems[i]))
|
}
|
||||||
return VAR(false);
|
return vm->True;
|
||||||
return VAR(true);
|
});
|
||||||
});
|
|
||||||
// clear the deque
|
// clear the deque
|
||||||
vm->bind(type, "clear(self) -> None",
|
vm->bind(type, "clear(self) -> None",
|
||||||
[](VM *vm, ArgsView args)
|
[](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)
|
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
|
// 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){
|
_vm->bind__repr__(VM::tp_list, [](VM* vm, PyObject* _0){
|
||||||
|
if(vm->_repr_recursion_set.count(_0)) return VAR("[...]");
|
||||||
List& iterable = _CAST(List&, _0);
|
List& iterable = _CAST(List&, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << '[';
|
ss << '[';
|
||||||
|
vm->_repr_recursion_set.insert(_0);
|
||||||
for(int i=0; i<iterable.size(); i++){
|
for(int i=0; i<iterable.size(); i++){
|
||||||
if(iterable[i] == _0){
|
ss << CAST(Str&, vm->py_repr(iterable[i]));
|
||||||
ss << "[...]";
|
|
||||||
}else{
|
|
||||||
ss << CAST(Str&, vm->py_repr(iterable[i]));
|
|
||||||
}
|
|
||||||
if(i != iterable.size()-1) ss << ", ";
|
if(i != iterable.size()-1) ss << ", ";
|
||||||
}
|
}
|
||||||
|
vm->_repr_recursion_set.erase(_0);
|
||||||
ss << ']';
|
ss << ']';
|
||||||
return VAR(ss.str());
|
return VAR(ss.str());
|
||||||
});
|
});
|
||||||
@ -1080,16 +1079,19 @@ void init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_mappingproxy, [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(VM::tp_mappingproxy, [](VM* vm, PyObject* _0) {
|
||||||
|
if(vm->_repr_recursion_set.count(_0)) return VAR("{...}");
|
||||||
MappingProxy& self = _CAST(MappingProxy&, _0);
|
MappingProxy& self = _CAST(MappingProxy&, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << "mappingproxy({";
|
ss << "mappingproxy({";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
vm->_repr_recursion_set.insert(_0);
|
||||||
for(auto& item : self.attr().items()){
|
for(auto& item : self.attr().items()){
|
||||||
if(!first) ss << ", ";
|
if(!first) ss << ", ";
|
||||||
first = false;
|
first = false;
|
||||||
ss << item.first.escape() << ": ";
|
ss << item.first.escape() << ": ";
|
||||||
ss << CAST(Str, vm->py_repr(item.second));
|
ss << CAST(Str, vm->py_repr(item.second));
|
||||||
}
|
}
|
||||||
|
vm->_repr_recursion_set.erase(_0);
|
||||||
ss << "})";
|
ss << "})";
|
||||||
return VAR(ss.str());
|
return VAR(ss.str());
|
||||||
});
|
});
|
||||||
@ -1227,20 +1229,18 @@ void init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_dict, [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(VM::tp_dict, [](VM* vm, PyObject* _0) {
|
||||||
|
if(vm->_repr_recursion_set.count(_0)) return VAR("{...}");
|
||||||
Dict& self = _CAST(Dict&, _0);
|
Dict& self = _CAST(Dict&, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << "{";
|
ss << "{";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
vm->_repr_recursion_set.insert(_0);
|
||||||
self.apply([&](PyObject* k, PyObject* v){
|
self.apply([&](PyObject* k, PyObject* v){
|
||||||
if(!first) ss << ", ";
|
if(!first) ss << ", ";
|
||||||
first = false;
|
first = false;
|
||||||
ss << CAST(Str&, vm->py_repr(k)) << ": ";
|
ss << CAST(Str&, vm->py_repr(k)) << ": " << CAST(Str&, vm->py_repr(v));
|
||||||
if(v == _0){
|
|
||||||
ss << "{...}";
|
|
||||||
}else{
|
|
||||||
ss << CAST(Str&, vm->py_repr(v));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
vm->_repr_recursion_set.erase(_0);
|
||||||
ss << "}";
|
ss << "}";
|
||||||
return VAR(ss.str());
|
return VAR(ss.str());
|
||||||
});
|
});
|
||||||
|
@ -97,7 +97,7 @@ assert b[
|
|||||||
0] == 1
|
0] == 1
|
||||||
|
|
||||||
a = []
|
a = []
|
||||||
a.append(1)
|
a.append(0)
|
||||||
a.append(a)
|
a.append([1, 2, a])
|
||||||
|
|
||||||
assert repr(a) == '[1, [...]]'
|
assert repr(a) == "[0, [1, 2, [...]]]"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user