mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
...
This commit is contained in:
parent
7916bb035f
commit
a12eb4c8bc
@ -231,7 +231,7 @@ Compare two python objects
|
||||
```cpp
|
||||
PyObject* obj1 = py_var(vm, 1);
|
||||
PyObject* obj2 = py_var(vm, 2);
|
||||
bool ok = vm->py_equals(obj1, obj2);
|
||||
bool ok = vm->py_eq(obj1, obj2);
|
||||
```
|
||||
|
||||
Convert a python object to string
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <bitset>
|
||||
#include <deque>
|
||||
|
||||
#define PK_VERSION "1.2.7"
|
||||
#define PK_VERSION "1.2.9"
|
||||
|
||||
#include "config.h"
|
||||
#include "export.h"
|
||||
|
@ -304,7 +304,12 @@ public:
|
||||
PK_OBJ_GET(NativeFunc, nf).set_userdata(f);
|
||||
}
|
||||
|
||||
bool py_equals(PyObject* lhs, PyObject* rhs);
|
||||
bool py_eq(PyObject* lhs, PyObject* rhs);
|
||||
// new in v1.2.9
|
||||
bool py_lt(PyObject* lhs, PyObject* rhs);
|
||||
bool py_le(PyObject* lhs, PyObject* rhs);
|
||||
bool py_gt(PyObject* lhs, PyObject* rhs);
|
||||
bool py_ge(PyObject* lhs, PyObject* rhs);
|
||||
|
||||
template<int ARGC>
|
||||
PyObject* bind_func(Str type, Str name, NativeFuncC fn) {
|
||||
|
@ -286,38 +286,6 @@ def __f(self, reverse=False, key=None):
|
||||
self.reverse()
|
||||
list.sort = __f
|
||||
|
||||
def __f(self, other):
|
||||
for i, j in zip(self, other):
|
||||
if i != j:
|
||||
return i < j
|
||||
return len(self) < len(other)
|
||||
tuple.__lt__ = __f
|
||||
list.__lt__ = __f
|
||||
|
||||
def __f(self, other):
|
||||
for i, j in zip(self, other):
|
||||
if i != j:
|
||||
return i > j
|
||||
return len(self) > len(other)
|
||||
tuple.__gt__ = __f
|
||||
list.__gt__ = __f
|
||||
|
||||
def __f(self, other):
|
||||
for i, j in zip(self, other):
|
||||
if i != j:
|
||||
return i <= j
|
||||
return len(self) <= len(other)
|
||||
tuple.__le__ = __f
|
||||
list.__le__ = __f
|
||||
|
||||
def __f(self, other):
|
||||
for i, j in zip(self, other):
|
||||
if i != j:
|
||||
return i >= j
|
||||
return len(self) >= len(other)
|
||||
tuple.__ge__ = __f
|
||||
list.__ge__ = __f
|
||||
|
||||
type.__repr__ = lambda self: "<class '" + self.__name__ + "'>"
|
||||
type.__getitem__ = lambda self, *args: self # for generics
|
||||
|
||||
|
@ -2,6 +2,48 @@
|
||||
|
||||
namespace pkpy{
|
||||
|
||||
#define BINARY_F_COMPARE(func, op, rfunc) \
|
||||
PyObject* ret; \
|
||||
const PyTypeInfo* _ti = _inst_type_info(_0); \
|
||||
if(_ti->m##func){ \
|
||||
ret = _ti->m##func(this, _0, _1); \
|
||||
}else{ \
|
||||
PyObject* self; \
|
||||
PyObject* _2 = get_unbound_method(_0, func, &self, false); \
|
||||
if(_2 != nullptr) ret = call_method(self, _2, _1); \
|
||||
else ret = NotImplemented; \
|
||||
} \
|
||||
if(ret == NotImplemented){ \
|
||||
PyObject* self; \
|
||||
PyObject* _2 = get_unbound_method(_1, rfunc, &self, false); \
|
||||
if(_2 != nullptr) ret = call_method(self, _2, _0); \
|
||||
else BinaryOptError(op); \
|
||||
if(ret == NotImplemented) BinaryOptError(op); \
|
||||
}
|
||||
|
||||
|
||||
bool VM::py_lt(PyObject* _0, PyObject* _1){
|
||||
BINARY_F_COMPARE(__lt__, "<", __gt__);
|
||||
return CAST(bool, ret);
|
||||
}
|
||||
|
||||
bool VM::py_le(PyObject* _0, PyObject* _1){
|
||||
BINARY_F_COMPARE(__le__, "<=", __ge__);
|
||||
return CAST(bool, ret);
|
||||
}
|
||||
|
||||
bool VM::py_gt(PyObject* _0, PyObject* _1){
|
||||
BINARY_F_COMPARE(__gt__, ">", __lt__);
|
||||
return CAST(bool, ret);
|
||||
}
|
||||
|
||||
bool VM::py_ge(PyObject* _0, PyObject* _1){
|
||||
BINARY_F_COMPARE(__ge__, ">=", __le__);
|
||||
return CAST(bool, ret);
|
||||
}
|
||||
|
||||
#undef BINARY_F_COMPARE
|
||||
|
||||
static i64 _py_sint(PyObject* obj) noexcept {
|
||||
return (i64)(PK_BITS(obj) >> 2);
|
||||
}
|
||||
@ -386,34 +428,34 @@ __NEXT_STEP:;
|
||||
if(TOP() == NotImplemented) BinaryOptError("%");
|
||||
} DISPATCH()
|
||||
TARGET(COMPARE_LT){
|
||||
PyObject* _0; PyObject* _1; const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__lt__);
|
||||
BINARY_OP_RSPECIAL("<", __gt__);
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
TOP() = VAR(py_lt(_0, _1));
|
||||
} DISPATCH()
|
||||
TARGET(COMPARE_LE){
|
||||
PyObject* _0; PyObject* _1; const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__le__);
|
||||
BINARY_OP_RSPECIAL("<=", __ge__);
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
TOP() = VAR(py_le(_0, _1));
|
||||
} DISPATCH()
|
||||
TARGET(COMPARE_EQ){
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
TOP() = VAR(py_equals(_0, _1));
|
||||
TOP() = VAR(py_eq(_0, _1));
|
||||
} DISPATCH()
|
||||
TARGET(COMPARE_NE){
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
TOP() = VAR(!py_equals(_0, _1));
|
||||
TOP() = VAR(!py_eq(_0, _1));
|
||||
} DISPATCH()
|
||||
TARGET(COMPARE_GT){
|
||||
PyObject* _0; PyObject* _1; const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__gt__);
|
||||
BINARY_OP_RSPECIAL(">", __lt__);
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
TOP() = VAR(py_gt(_0, _1));
|
||||
} DISPATCH()
|
||||
TARGET(COMPARE_GE){
|
||||
PyObject* _0; PyObject* _1; const PyTypeInfo* _ti;
|
||||
BINARY_OP_SPECIAL(__ge__);
|
||||
BINARY_OP_RSPECIAL(">=", __le__);
|
||||
PyObject* _1 = POPX();
|
||||
PyObject* _0 = TOP();
|
||||
TOP() = VAR(py_ge(_0, _1));
|
||||
} DISPATCH()
|
||||
TARGET(BITWISE_LSHIFT){
|
||||
PyObject* _0; PyObject* _1; const PyTypeInfo* _ti;
|
||||
|
@ -145,7 +145,7 @@ namespace pkpy
|
||||
if (self.dequeItems.size() != other.dequeItems.size()) // trivial case
|
||||
return VAR(false);
|
||||
for (int i = 0; i < self.dequeItems.size(); i++)
|
||||
if (!vm->py_equals(self.dequeItems[i], other.dequeItems[i]))
|
||||
if (!vm->py_eq(self.dequeItems[i], other.dequeItems[i]))
|
||||
return VAR(false);
|
||||
return VAR(true);
|
||||
});
|
||||
@ -235,7 +235,7 @@ namespace pkpy
|
||||
int cnt = 0, sz = self.dequeItems.size();
|
||||
for (auto it = self.dequeItems.begin(); it != self.dequeItems.end(); ++it)
|
||||
{
|
||||
if (vm->py_equals((*it), obj))
|
||||
if (vm->py_eq((*it), obj))
|
||||
cnt++;
|
||||
if (sz != self.dequeItems.size())// mutating the deque during iteration is not allowed
|
||||
vm->RuntimeError("deque mutated during iteration");
|
||||
@ -265,9 +265,9 @@ namespace pkpy
|
||||
PyDeque &self = _CAST(PyDeque &, args[0]);
|
||||
PyObject *obj = args[1];
|
||||
int start = 0, stop = self.dequeItems.size(); // default values
|
||||
if (!vm->py_equals(args[2], vm->None))
|
||||
if (!vm->py_eq(args[2], vm->None))
|
||||
start = CAST(int, args[2]);
|
||||
if (!vm->py_equals(args[3], vm->None))
|
||||
if (!vm->py_eq(args[3], vm->None))
|
||||
stop = CAST(int, args[3]);
|
||||
int index = self.findIndex(vm, obj, start, stop);
|
||||
if (index != -1)
|
||||
@ -398,7 +398,7 @@ namespace pkpy
|
||||
PyDeque::PyDeque(VM *vm, PyObject *iterable, PyObject *maxlen)
|
||||
{
|
||||
|
||||
if (!vm->py_equals(maxlen, vm->None)) // fix the maxlen first
|
||||
if (!vm->py_eq(maxlen, vm->None)) // fix the maxlen first
|
||||
{
|
||||
int tmp = CAST(int, maxlen);
|
||||
if (tmp < 0)
|
||||
@ -414,7 +414,7 @@ namespace pkpy
|
||||
this->bounded = false;
|
||||
this->maxlen = -1;
|
||||
}
|
||||
if (!vm->py_equals(iterable, vm->None))
|
||||
if (!vm->py_eq(iterable, vm->None))
|
||||
{
|
||||
this->dequeItems.clear(); // clear the deque
|
||||
auto _lock = vm->heap.gc_scope_lock(); // locking the heap
|
||||
@ -467,7 +467,7 @@ namespace pkpy
|
||||
int sz = this->dequeItems.size();
|
||||
for (int i = start; i < loopSize; i++)
|
||||
{
|
||||
if (vm->py_equals(this->dequeItems[i], obj))
|
||||
if (vm->py_eq(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");
|
||||
@ -479,7 +479,7 @@ namespace pkpy
|
||||
/// @param front if true, pop from the front of the deque
|
||||
/// @param back if true, pop from the back of the deque
|
||||
/// @param item if front and back is not set, remove the first occurence of item from the deque
|
||||
/// @param vm is needed for the py_equals
|
||||
/// @param vm is needed for the py_eq
|
||||
/// @return PyObject* if front or back is set, this is a pop operation and we return a PyObject*, if front and back are not set, this is a remove operation and we return the removed item or nullptr
|
||||
PyObject *PyDeque::popObj(bool front, bool back, PyObject *item, VM *vm)
|
||||
{
|
||||
@ -510,7 +510,7 @@ namespace pkpy
|
||||
int sz = this->dequeItems.size();
|
||||
for (auto it = this->dequeItems.begin(); it != this->dequeItems.end(); ++it)
|
||||
{
|
||||
bool found = vm->py_equals((*it), item);
|
||||
bool found = vm->py_eq((*it), item);
|
||||
if (sz != this->dequeItems.size()) // mutating the deque during iteration is not allowed
|
||||
vm->IndexError("deque mutated during iteration");
|
||||
if (found)
|
||||
|
@ -736,14 +736,14 @@ void init_builtins(VM* _vm) {
|
||||
|
||||
_vm->bind__contains__(_vm->tp_list, [](VM* vm, PyObject* obj, PyObject* item) {
|
||||
List& self = _CAST(List&, obj);
|
||||
for(PyObject* i: self) if(vm->py_equals(i, item)) return vm->True;
|
||||
for(PyObject* i: self) if(vm->py_eq(i, item)) return vm->True;
|
||||
return vm->False;
|
||||
});
|
||||
|
||||
_vm->bind_method<1>("list", "count", [](VM* vm, ArgsView args) {
|
||||
List& self = _CAST(List&, args[0]);
|
||||
int count = 0;
|
||||
for(PyObject* i: self) if(vm->py_equals(i, args[1])) count++;
|
||||
for(PyObject* i: self) if(vm->py_eq(i, args[1])) count++;
|
||||
return VAR(count);
|
||||
});
|
||||
|
||||
@ -753,7 +753,7 @@ void init_builtins(VM* _vm) {
|
||||
List& b = _CAST(List&, rhs);
|
||||
if(a.size() != b.size()) return vm->False;
|
||||
for(int i=0; i<a.size(); i++){
|
||||
if(!vm->py_equals(a[i], b[i])) return vm->False;
|
||||
if(!vm->py_eq(a[i], b[i])) return vm->False;
|
||||
}
|
||||
return vm->True;
|
||||
});
|
||||
@ -762,7 +762,7 @@ void init_builtins(VM* _vm) {
|
||||
List& self = _CAST(List&, args[0]);
|
||||
PyObject* obj = args[1];
|
||||
for(int i=0; i<self.size(); i++){
|
||||
if(vm->py_equals(self[i], obj)) return VAR(i);
|
||||
if(vm->py_eq(self[i], obj)) return VAR(i);
|
||||
}
|
||||
vm->ValueError(_CAST(Str&, vm->py_repr(obj)) + " is not in list");
|
||||
return vm->None;
|
||||
@ -772,7 +772,7 @@ void init_builtins(VM* _vm) {
|
||||
List& self = _CAST(List&, args[0]);
|
||||
PyObject* obj = args[1];
|
||||
for(int i=0; i<self.size(); i++){
|
||||
if(vm->py_equals(self[i], obj)){
|
||||
if(vm->py_eq(self[i], obj)){
|
||||
self.erase(i);
|
||||
return vm->None;
|
||||
}
|
||||
@ -858,6 +858,30 @@ void init_builtins(VM* _vm) {
|
||||
|
||||
_vm->bind_method<0>("list", "copy", PK_LAMBDA(VAR(_CAST(List, args[0]))));
|
||||
|
||||
#define BIND_RICH_CMP(name, op, _t, _T) \
|
||||
_vm->bind__##name##__(_vm->_t, [](VM* vm, PyObject* lhs, PyObject* rhs){ \
|
||||
if(!is_non_tagged_type(rhs, vm->_t)) return vm->NotImplemented; \
|
||||
auto& a = _CAST(_T&, lhs); \
|
||||
auto& b = _CAST(_T&, rhs); \
|
||||
for(int i=0; i<a.size() && i<b.size(); i++){ \
|
||||
if(vm->py_eq(a[i], b[i])) continue; \
|
||||
return VAR(vm->py_##name(a[i], b[i])); \
|
||||
} \
|
||||
return VAR(a.size() op b.size()); \
|
||||
});
|
||||
|
||||
BIND_RICH_CMP(lt, <, tp_list, List)
|
||||
BIND_RICH_CMP(le, <=, tp_list, List)
|
||||
BIND_RICH_CMP(gt, >, tp_list, List)
|
||||
BIND_RICH_CMP(ge, >=, tp_list, List)
|
||||
|
||||
BIND_RICH_CMP(lt, <, tp_tuple, Tuple)
|
||||
BIND_RICH_CMP(le, <=, tp_tuple, Tuple)
|
||||
BIND_RICH_CMP(gt, >, tp_tuple, Tuple)
|
||||
BIND_RICH_CMP(ge, >=, tp_tuple, Tuple)
|
||||
|
||||
#undef BIND_RICH_CMP
|
||||
|
||||
_vm->bind__add__(_vm->tp_list, [](VM* vm, PyObject* lhs, PyObject* rhs) {
|
||||
const List& self = _CAST(List&, lhs);
|
||||
const List& other = CAST(List&, rhs);
|
||||
@ -900,14 +924,14 @@ void init_builtins(VM* _vm) {
|
||||
|
||||
_vm->bind__contains__(_vm->tp_tuple, [](VM* vm, PyObject* obj, PyObject* item) {
|
||||
Tuple& self = _CAST(Tuple&, obj);
|
||||
for(PyObject* i: self) if(vm->py_equals(i, item)) return vm->True;
|
||||
for(PyObject* i: self) if(vm->py_eq(i, item)) return vm->True;
|
||||
return vm->False;
|
||||
});
|
||||
|
||||
_vm->bind_method<1>("tuple", "count", [](VM* vm, ArgsView args) {
|
||||
Tuple& self = _CAST(Tuple&, args[0]);
|
||||
int count = 0;
|
||||
for(PyObject* i: self) if(vm->py_equals(i, args[1])) count++;
|
||||
for(PyObject* i: self) if(vm->py_eq(i, args[1])) count++;
|
||||
return VAR(count);
|
||||
});
|
||||
|
||||
@ -917,7 +941,7 @@ void init_builtins(VM* _vm) {
|
||||
const Tuple& other = _CAST(Tuple&, rhs);
|
||||
if(self.size() != other.size()) return vm->False;
|
||||
for(int i = 0; i < self.size(); i++) {
|
||||
if(!vm->py_equals(self[i], other[i])) return vm->False;
|
||||
if(!vm->py_eq(self[i], other[i])) return vm->False;
|
||||
}
|
||||
return vm->True;
|
||||
});
|
||||
@ -1282,7 +1306,7 @@ void init_builtins(VM* _vm) {
|
||||
if(item.first == nullptr) continue;
|
||||
PyObject* value = other.try_get(item.first);
|
||||
if(value == nullptr) return vm->False;
|
||||
if(!vm->py_equals(item.second, value)) return vm->False;
|
||||
if(!vm->py_eq(item.second, value)) return vm->False;
|
||||
}
|
||||
return vm->True;
|
||||
});
|
||||
|
@ -249,7 +249,7 @@ namespace pkpy{
|
||||
return &_all_types[obj->type];
|
||||
}
|
||||
|
||||
bool VM::py_equals(PyObject* lhs, PyObject* rhs){
|
||||
bool VM::py_eq(PyObject* lhs, PyObject* rhs){
|
||||
if(lhs == rhs) return true;
|
||||
const PyTypeInfo* ti = _inst_type_info(lhs);
|
||||
PyObject* res;
|
||||
@ -1230,7 +1230,7 @@ void Dict::_probe_0(PyObject *key, bool &ok, int &i) const{
|
||||
// std::cout << CAST(Str, vm->py_repr(key)) << " " << hash << " " << i << std::endl;
|
||||
for(int j=0; j<_capacity; j++) {
|
||||
if(_items[i].first != nullptr){
|
||||
if(vm->py_equals(_items[i].first, key)) { ok = true; break; }
|
||||
if(vm->py_eq(_items[i].first, key)) { ok = true; break; }
|
||||
}else{
|
||||
if(_items[i].second == nullptr) break;
|
||||
}
|
||||
@ -1244,7 +1244,7 @@ void Dict::_probe_1(PyObject *key, bool &ok, int &i) const{
|
||||
ok = false;
|
||||
i = vm->py_hash(key) & _mask;
|
||||
while(_items[i].first != nullptr) {
|
||||
if(vm->py_equals(_items[i].first, key)) { ok = true; break; }
|
||||
if(vm->py_eq(_items[i].first, key)) { ok = true; break; }
|
||||
// https://github.com/python/cpython/blob/3.8/Objects/dictobject.c#L166
|
||||
i = ((5*i) + 1) & _mask;
|
||||
}
|
||||
|
@ -826,6 +826,3 @@ d = deque()
|
||||
for i in range(100):
|
||||
d.append(1)
|
||||
gc.collect()
|
||||
|
||||
|
||||
print('✓', "ALL TEST PASSED!!")
|
||||
|
@ -380,7 +380,7 @@ except:
|
||||
# #####: 649: List& self = _CAST(List&, args[0]);
|
||||
# #####: 650: PyObject* obj = args[1];
|
||||
# #####: 651: for(int i=0; i<self.size(); i++){
|
||||
# #####: 652: if(vm->py_equals(self[i], obj)) return VAR(i);
|
||||
# #####: 652: if(vm->py_eq(self[i], obj)) return VAR(i);
|
||||
# -: 653: }
|
||||
# #####: 654: vm->ValueError(_CAST(Str&, vm->py_repr(obj)) + " is not in list");
|
||||
# #####: 655: return vm->None;
|
||||
@ -401,7 +401,7 @@ except:
|
||||
# 1: 659: List& self = _CAST(List&, args[0]);
|
||||
# 1: 660: PyObject* obj = args[1];
|
||||
# 2: 661: for(int i=0; i<self.size(); i++){
|
||||
# 2: 662: if(vm->py_equals(self[i], obj)){
|
||||
# 2: 662: if(vm->py_eq(self[i], obj)){
|
||||
# 1: 663: self.erase(i);
|
||||
# 1: 664: return vm->None;
|
||||
# -: 665: }
|
||||
@ -474,7 +474,7 @@ except:
|
||||
# 未完全测试准确性-----------------------------------------------
|
||||
# 118: 793: _vm->bind__contains__(_vm->tp_tuple, [](VM* vm, PyObject* obj, PyObject* item) {
|
||||
# 1: 794: Tuple& self = _CAST(Tuple&, obj);
|
||||
# 3: 795: for(PyObject* i: self) if(vm->py_equals(i, item)) return vm->True;
|
||||
# 3: 795: for(PyObject* i: self) if(vm->py_eq(i, item)) return vm->True;
|
||||
# #####: 796: return vm->False;
|
||||
# 1: 797: });
|
||||
# test tuple.__contains__:
|
||||
@ -485,7 +485,7 @@ assert (1,2,3).__contains__(5) == False
|
||||
# 116: 799: _vm->bind_method<1>("tuple", "count", [](VM* vm, ArgsView args) {
|
||||
# #####: 800: Tuple& self = _CAST(Tuple&, args[0]);
|
||||
# -: 801: int count = 0;
|
||||
# #####: 802: for(PyObject* i: self) if(vm->py_equals(i, args[1])) count++;
|
||||
# #####: 802: for(PyObject* i: self) if(vm->py_eq(i, args[1])) count++;
|
||||
# #####: 803: return VAR(count);
|
||||
# -: 804: });
|
||||
# test tuple.count:
|
||||
|
Loading…
x
Reference in New Issue
Block a user