diff --git a/include/pocketpy/interpreter/vm.h b/include/pocketpy/interpreter/vm.h index 12d10fba..62108e6d 100644 --- a/include/pocketpy/interpreter/vm.h +++ b/include/pocketpy/interpreter/vm.h @@ -94,7 +94,7 @@ int pk_arrayequal(py_TValue* lhs, int lhs_length, py_TValue* rhs, int rhs_length bool pk_arrayiter(py_Ref val); bool pk_arraycontains(py_Ref self, py_Ref val); -bool pk_pushmethod(py_StackRef self, py_Name name); +bool pk_loadmethod(py_StackRef self, py_Name name); bool pk_callmagic(py_Name name, int argc, py_Ref argv); /// Assumes [a, b] are on the stack, performs a binary op. diff --git a/src/common/sstream.c b/src/common/sstream.c index 8fb6c715..425e6901 100644 --- a/src/common/sstream.c +++ b/src/common/sstream.c @@ -234,7 +234,7 @@ void pk_sprintf(c11_sbuf* ss, const char* fmt, ...) { } int py_replinput(char* buf, int max_size) { - buf[0] = '\0'; + buf[0] = '\0'; // reset first char because we check '@' at the beginning int size = 0; bool multiline = false; diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 590877a4..51c43f1e 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -484,7 +484,7 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall } // handle `__call__` overload - if(pk_pushmethod(p0, __call__)) { + if(pk_loadmethod(p0, __call__)) { // [__call__, self, args..., kwargs...] return VM__vectorcall(self, argc, kwargc, opcall); } diff --git a/src/public/internal.c b/src/public/internal.c index 18208369..ed669c58 100644 --- a/src/public/internal.c +++ b/src/public/internal.c @@ -231,9 +231,13 @@ bool py_vectorcall(uint16_t argc, uint16_t kwargc) { py_Ref py_retval() { return &pk_current_vm->last_retval; } -bool py_pushmethod(py_Name name) { return pk_pushmethod(py_peek(-1), name); } +bool py_pushmethod(py_Name name) { + bool ok = pk_loadmethod(py_peek(-1), name); + if(ok) pk_current_vm->stack.sp++; + return ok; +} -bool pk_pushmethod(py_StackRef self, py_Name name) { +bool pk_loadmethod(py_StackRef self, py_Name name) { // NOTE: `out` and `out_self` may overlap with `self` py_Type type; // handle super() proxy @@ -246,7 +250,6 @@ bool pk_pushmethod(py_StackRef self, py_Name name) { py_Ref cls_var = py_tpfindname(type, name); if(cls_var != NULL) { - pk_current_vm->stack.sp++; switch(cls_var->type) { case tp_function: case tp_nativefunc: { diff --git a/src/public/py_str.c b/src/public/py_str.c index 45178943..c6df8f15 100644 --- a/src/public/py_str.c +++ b/src/public/py_str.c @@ -72,7 +72,7 @@ static bool str__hash__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); int size; const char* data = py_tostrn(&argv[0], &size); - py_i64 res = 0; + uint64_t res = 0; for(int i = 0; i < size; i++) { res = res * 31 + data[i]; } diff --git a/src/public/py_tuple.c b/src/public/py_tuple.c index 344d4d1c..4c381147 100644 --- a/src/public/py_tuple.c +++ b/src/public/py_tuple.c @@ -131,6 +131,21 @@ static bool tuple__contains__(int argc, py_Ref argv) { return pk_arraycontains(py_arg(0), py_arg(1)); } +static bool tuple__hash__(int argc, py_Ref argv) { + PY_CHECK_ARGC(1); + int length = py_tuple__len(argv); + py_TValue* data = py_tuple__data(argv); + uint64_t x = 1000003; + for(int i = 0; i < length; i++) { + py_i64 y; + if(!py_hash(&data[i], &y)) return false; + // recommended by Github Copilot + x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2)); + } + py_newint(py_retval(), x); + return true; +} + py_Type pk_tuple__register() { py_Type type = pk_newtype("tuple", tp_object, NULL, NULL, false, true); @@ -142,5 +157,6 @@ py_Type pk_tuple__register() { py_bindmagic(type, __ne__, tuple__ne__); py_bindmagic(type, __iter__, tuple__iter__); py_bindmagic(type, __contains__, tuple__contains__); + py_bindmagic(type, __hash__, tuple__hash__); return type; } diff --git a/tests/42_decorator.py b/tests/42_decorator.py index b90f8321..98d7fba0 100644 --- a/tests/42_decorator.py +++ b/tests/42_decorator.py @@ -8,8 +8,12 @@ class A: def x(self): return self._x + def __call__(self, b): + return self.x + b + a = A(1) assert a.x == 1 +assert a(2) == 3 class B: def __init__(self): @@ -28,9 +32,6 @@ assert b.x == 1 b.x = 2 assert b.x == 2 - -@cache -@cache @cache def fib(n): # print(f'fib({n})') @@ -76,5 +77,3 @@ def f(): f() assert res == ['w2', 'w1', 'w'] - -