mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
reimpl py_hash
This commit is contained in:
parent
d4a90c9788
commit
53ea790caf
@ -16,7 +16,7 @@ Methods return a `bool` indicating if the operation succeeded or not.
|
|||||||
Special thanks for [@koltenpearson](https://github.com/koltenpearson)'s contribution.
|
Special thanks for [@koltenpearson](https://github.com/koltenpearson)'s contribution.
|
||||||
|
|
||||||
!!!
|
!!!
|
||||||
**C-APIs are always stable and backward compatible** in order to support the second use case.
|
C-APIs are always stable and backward compatible.
|
||||||
!!!
|
!!!
|
||||||
|
|
||||||
### Basic functions
|
### Basic functions
|
||||||
|
@ -309,7 +309,6 @@ void init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__eq__(_vm->tp_object, [](VM* vm, PyObject* lhs, PyObject* rhs) { return VAR(lhs == rhs); });
|
_vm->bind__eq__(_vm->tp_object, [](VM* vm, PyObject* lhs, PyObject* rhs) { return VAR(lhs == rhs); });
|
||||||
_vm->bind__hash__(_vm->tp_object, [](VM* vm, PyObject* obj) { return PK_BITS(obj); });
|
|
||||||
|
|
||||||
_vm->cached_object__new__ = _vm->bind_constructor<1>("object", [](VM* vm, ArgsView args) {
|
_vm->cached_object__new__ = _vm->bind_constructor<1>("object", [](VM* vm, ArgsView args) {
|
||||||
vm->check_non_tagged_type(args[0], vm->tp_type);
|
vm->check_non_tagged_type(args[0], vm->tp_type);
|
||||||
@ -754,11 +753,6 @@ void init_builtins(VM* _vm) {
|
|||||||
|
|
||||||
_vm->bind_method<0>("list", "copy", PK_LAMBDA(VAR(_CAST(List, args[0]))));
|
_vm->bind_method<0>("list", "copy", PK_LAMBDA(VAR(_CAST(List, args[0]))));
|
||||||
|
|
||||||
_vm->bind__hash__(_vm->tp_list, [](VM* vm, PyObject* obj) {
|
|
||||||
vm->TypeError("unhashable type: 'list'");
|
|
||||||
return (i64)0;
|
|
||||||
});
|
|
||||||
|
|
||||||
_vm->bind__add__(_vm->tp_list, [](VM* vm, PyObject* lhs, PyObject* rhs) {
|
_vm->bind__add__(_vm->tp_list, [](VM* vm, PyObject* lhs, PyObject* rhs) {
|
||||||
const List& self = _CAST(List&, lhs);
|
const List& self = _CAST(List&, lhs);
|
||||||
const List& other = CAST(List&, rhs);
|
const List& other = CAST(List&, rhs);
|
||||||
@ -997,9 +991,13 @@ void init_builtins(VM* _vm) {
|
|||||||
return (i64)_CAST(MappingProxy&, obj).attr().size();
|
return (i64)_CAST(MappingProxy&, obj).attr().size();
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__hash__(_vm->tp_mappingproxy, [](VM* vm, PyObject* obj) {
|
_vm->bind__eq__(_vm->tp_mappingproxy, [](VM* vm, PyObject* obj, PyObject* other){
|
||||||
vm->TypeError("unhashable type: 'mappingproxy'");
|
MappingProxy& a = _CAST(MappingProxy&, obj);
|
||||||
return (i64)0;
|
if(!is_non_tagged_type(other, vm->tp_mappingproxy)){
|
||||||
|
return vm->NotImplemented;
|
||||||
|
}
|
||||||
|
MappingProxy& b = _CAST(MappingProxy&, other);
|
||||||
|
return VAR(a.obj == b.obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__getitem__(_vm->tp_mappingproxy, [](VM* vm, PyObject* obj, PyObject* index) {
|
_vm->bind__getitem__(_vm->tp_mappingproxy, [](VM* vm, PyObject* obj, PyObject* index) {
|
||||||
@ -1058,11 +1056,6 @@ void init_builtins(VM* _vm) {
|
|||||||
return (i64)_CAST(Dict&, obj).size();
|
return (i64)_CAST(Dict&, obj).size();
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__hash__(_vm->tp_dict, [](VM* vm, PyObject* obj) {
|
|
||||||
vm->TypeError("unhashable type: 'dict'");
|
|
||||||
return (i64)0;
|
|
||||||
});
|
|
||||||
|
|
||||||
_vm->bind__getitem__(_vm->tp_dict, [](VM* vm, PyObject* obj, PyObject* index) {
|
_vm->bind__getitem__(_vm->tp_dict, [](VM* vm, PyObject* obj, PyObject* index) {
|
||||||
Dict& self = _CAST(Dict&, obj);
|
Dict& self = _CAST(Dict&, obj);
|
||||||
PyObject* ret = self.try_get(index);
|
PyObject* ret = self.try_get(index);
|
||||||
|
21
src/vm.cpp
21
src/vm.cpp
@ -350,11 +350,30 @@ void VM::parse_int_slice(const Slice& s, int length, int& start, int& stop, int&
|
|||||||
}
|
}
|
||||||
|
|
||||||
i64 VM::py_hash(PyObject* obj){
|
i64 VM::py_hash(PyObject* obj){
|
||||||
|
// https://docs.python.org/3.10/reference/datamodel.html#object.__hash__
|
||||||
const PyTypeInfo* ti = _inst_type_info(obj);
|
const PyTypeInfo* ti = _inst_type_info(obj);
|
||||||
if(ti->m__hash__) return ti->m__hash__(this, obj);
|
if(ti->m__hash__) return ti->m__hash__(this, obj);
|
||||||
PyObject* ret = call_method(obj, __hash__);
|
|
||||||
|
PyObject* self;
|
||||||
|
PyObject* f = get_unbound_method(obj, __hash__, &self, false);
|
||||||
|
if(f != nullptr){
|
||||||
|
PyObject* ret = call_method(self, f);
|
||||||
return CAST(i64, ret);
|
return CAST(i64, ret);
|
||||||
}
|
}
|
||||||
|
// it flow reaches here, obj must not be the trivial `object` type
|
||||||
|
bool has_custom_eq = false;
|
||||||
|
if(ti->m__eq__) has_custom_eq = true;
|
||||||
|
else{
|
||||||
|
f = get_unbound_method(obj, __eq__, &self, false);
|
||||||
|
has_custom_eq = f != _t(tp_object)->attr(__eq__);
|
||||||
|
}
|
||||||
|
if(has_custom_eq){
|
||||||
|
TypeError(fmt("unhashable type: ", ti->name.escape()));
|
||||||
|
return 0;
|
||||||
|
}else{
|
||||||
|
return PK_BITS(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PyObject* VM::format(Str spec, PyObject* obj){
|
PyObject* VM::format(Str spec, PyObject* obj){
|
||||||
if(spec.empty()) return py_str(obj);
|
if(spec.empty()) return py_str(obj);
|
||||||
|
@ -207,12 +207,12 @@ def f():
|
|||||||
assert type(hash(a)) is int
|
assert type(hash(a)) is int
|
||||||
|
|
||||||
# 测试不可哈希对象
|
# 测试不可哈希对象
|
||||||
# try:
|
try:
|
||||||
# hash({1:1})
|
hash({1:1})
|
||||||
# print('未能拦截错误')
|
print('未能拦截错误')
|
||||||
# exit(1)
|
exit(1)
|
||||||
# except:
|
except:
|
||||||
# pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
hash([1])
|
hash([1])
|
||||||
@ -842,7 +842,7 @@ try:
|
|||||||
hash(my_mappingproxy)
|
hash(my_mappingproxy)
|
||||||
print('未能拦截错误, 在测试 mappingproxy.__hash__')
|
print('未能拦截错误, 在测试 mappingproxy.__hash__')
|
||||||
exit(1)
|
exit(1)
|
||||||
except:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# 未完全测试准确性-----------------------------------------------
|
# 未完全测试准确性-----------------------------------------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user