blueloveTH 1 год назад
Родитель
Сommit
04804ad410

+ 1 - 1
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.

+ 1 - 1
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;

+ 1 - 1
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);
     }

+ 6 - 3
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: {

+ 1 - 1
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];
     }

+ 16 - 0
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;
 }

+ 4 - 5
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']
-
-