فهرست منبع

fix direct call of `__new__`

blueloveTH 1 سال پیش
والد
کامیت
46e92166d5
4فایلهای تغییر یافته به همراه24 افزوده شده و 2 حذف شده
  1. 4 0
      include/pocketpy/interpreter/vm.h
  2. 13 1
      src/public/internal.c
  3. 4 1
      src/public/py_ops.c
  4. 3 0
      tests/99_bugs.py

+ 4 - 0
include/pocketpy/interpreter/vm.h

@@ -10,6 +10,10 @@
 // 1. __eq__ and __ne__ fallbacks
 // 2. un-cleared exception detection
 // 3. super()
+// 4. stack balance guanrantee
+// 5. stack effect of each opcode
+// 6. py_TypeInfo
+// 7. Direct assignment of py_NIL, py_True, py_False, py_None. They are slow.
 
 typedef struct py_TypeInfo {
     py_Name name;

+ 13 - 1
src/public/internal.c

@@ -78,7 +78,6 @@ void py_sys_setargv(int argc, char** argv) {
 
 py_Callbacks* py_getcallbacks() { return &pk_current_vm->callbacks; }
 
-
 const char* pk_opname(Opcode op) {
     const static char* OP_NAMES[] = {
 #define OPCODE(name) #name,
@@ -140,6 +139,19 @@ bool py_pushmethod(py_Name name) {
 
 bool pk_loadmethod(py_StackRef self, py_Name name) {
     // NOTE: `out` and `out_self` may overlap with `self`
+
+    if(name == __new__ && py_istype(self, tp_type)) {
+        // __new__ acts like a @staticmethod
+        // T.__new__(...)
+        py_Ref cls_var = py_tpfindmagic(py_totype(self), name);
+        if(cls_var) {
+            self[0] = *cls_var;
+            self[1] = *py_NIL;
+            return true;
+        }
+        return false;
+    }
+
     py_Type type;
     // handle super() proxy
     if(py_istype(self, tp_super)) {

+ 4 - 1
src/public/py_ops.c

@@ -129,10 +129,12 @@ bool py_getattr(py_Ref self, py_Name name) {
         // bound method is non-data descriptor
         switch(cls_var->type) {
             case tp_function: {
+                if(name == __new__) goto __STATIC_NEW;
                 py_newboundmethod(py_retval(), self, cls_var);
                 return true;
             }
             case tp_nativefunc: {
+                if(name == __new__) goto __STATIC_NEW;
                 py_newboundmethod(py_retval(), self, cls_var);
                 return true;
             }
@@ -145,6 +147,7 @@ bool py_getattr(py_Ref self, py_Name name) {
                 return true;
             }
             default: {
+            __STATIC_NEW:
                 py_assign(py_retval(), cls_var);
                 return true;
             }
@@ -152,7 +155,7 @@ bool py_getattr(py_Ref self, py_Name name) {
     }
 
     py_Ref fallback = py_tpfindmagic(type, __getattr__);
-    if(fallback){
+    if(fallback) {
         py_push(fallback);
         py_push(self);
         py_newstr(py_pushtmp(), py_name2str(name));

+ 3 - 0
tests/99_bugs.py

@@ -134,3 +134,6 @@ a = [1, 10, 3]
 a[test()] += 1
 assert (a == [1, 11, 3]), a
 assert (g == 1), g
+
+assert list.__new__(list) == []
+assert a.__new__ == list.__new__