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.
|
||||
|
||||
!!!
|
||||
**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
|
||||
|
@ -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__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->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__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) {
|
||||
const List& self = _CAST(List&, lhs);
|
||||
const List& other = CAST(List&, rhs);
|
||||
@ -997,9 +991,13 @@ void init_builtins(VM* _vm) {
|
||||
return (i64)_CAST(MappingProxy&, obj).attr().size();
|
||||
});
|
||||
|
||||
_vm->bind__hash__(_vm->tp_mappingproxy, [](VM* vm, PyObject* obj) {
|
||||
vm->TypeError("unhashable type: 'mappingproxy'");
|
||||
return (i64)0;
|
||||
_vm->bind__eq__(_vm->tp_mappingproxy, [](VM* vm, PyObject* obj, PyObject* other){
|
||||
MappingProxy& a = _CAST(MappingProxy&, obj);
|
||||
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) {
|
||||
@ -1058,11 +1056,6 @@ void init_builtins(VM* _vm) {
|
||||
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) {
|
||||
Dict& self = _CAST(Dict&, obj);
|
||||
PyObject* ret = self.try_get(index);
|
||||
|
23
src/vm.cpp
23
src/vm.cpp
@ -350,10 +350,29 @@ void VM::parse_int_slice(const Slice& s, int length, int& start, int& stop, int&
|
||||
}
|
||||
|
||||
i64 VM::py_hash(PyObject* obj){
|
||||
// https://docs.python.org/3.10/reference/datamodel.html#object.__hash__
|
||||
const PyTypeInfo* ti = _inst_type_info(obj);
|
||||
if(ti->m__hash__) return ti->m__hash__(this, obj);
|
||||
PyObject* ret = call_method(obj, __hash__);
|
||||
return CAST(i64, ret);
|
||||
|
||||
PyObject* self;
|
||||
PyObject* f = get_unbound_method(obj, __hash__, &self, false);
|
||||
if(f != nullptr){
|
||||
PyObject* ret = call_method(self, f);
|
||||
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){
|
||||
|
@ -207,12 +207,12 @@ def f():
|
||||
assert type(hash(a)) is int
|
||||
|
||||
# 测试不可哈希对象
|
||||
# try:
|
||||
# hash({1:1})
|
||||
# print('未能拦截错误')
|
||||
# exit(1)
|
||||
# except:
|
||||
# pass
|
||||
try:
|
||||
hash({1:1})
|
||||
print('未能拦截错误')
|
||||
exit(1)
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
hash([1])
|
||||
@ -842,7 +842,7 @@ try:
|
||||
hash(my_mappingproxy)
|
||||
print('未能拦截错误, 在测试 mappingproxy.__hash__')
|
||||
exit(1)
|
||||
except:
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
# 未完全测试准确性-----------------------------------------------
|
||||
|
Loading…
x
Reference in New Issue
Block a user