Просмотр исходного кода

fix 'self' for get method from `getattr`

lyon 3 лет назад
Родитель
Сommit
ae2ec0a7cd

+ 2 - 3
package/PikaStdLib/PikaStdLib_SysObj.c

@@ -578,13 +578,12 @@ Arg* PikaStdLib_SysObj_getattr(PikaObj* self, PikaObj* obj, char* name) {
     Arg* arg = obj_getArg(obj, name);
     if (NULL == arg) {
         arg = obj_getMethodArg(obj, name);
-        return arg_copy(arg);
     }
     if (NULL != arg) {
         res = arg_copy(arg);
-        return res;
+        methodArg_setHostObj(res, obj);
     }
-    return NULL;
+    return res;
 }
 
 void PikaStdLib_SysObj_setattr(PikaObj* self,

+ 1 - 1
port/linux/.vscode/launch.json

@@ -11,7 +11,7 @@
             "program": "${workspaceFolder}/build/test/pikascript_test",
             // "program": "${workspaceFolder}/build/boot/demo06-pikamain/pikascript_demo06-pikamain",
             "args": [
-                "--gtest_filter=parser.not_in_or"
+                "--gtest_filter=vm.getattr_native"
             ],
             "stopAtEntry": false,
             "cwd": "${workspaceFolder}",

+ 2 - 3
port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdLib_SysObj.c

@@ -578,13 +578,12 @@ Arg* PikaStdLib_SysObj_getattr(PikaObj* self, PikaObj* obj, char* name) {
     Arg* arg = obj_getArg(obj, name);
     if (NULL == arg) {
         arg = obj_getMethodArg(obj, name);
-        return arg_copy(arg);
     }
     if (NULL != arg) {
         res = arg_copy(arg);
-        return res;
+        methodArg_setHostObj(res, obj);
     }
-    return NULL;
+    return res;
 }
 
 void PikaStdLib_SysObj_setattr(PikaObj* self,

+ 9 - 9
src/PikaObj.c

@@ -429,19 +429,16 @@ exit:
 }
 
 Arg* _obj_getMethodArg(PikaObj* obj, char* methodPath, Arg* arg_reg) {
-    Arg* method = NULL;
+    Arg* aMethod = NULL;
     char* methodName = strPointToLastToken(methodPath, '.');
-    method = obj_getArg(obj, methodName);
-    if (NULL != method) {
-        method = arg_copy_noalloc(method, arg_reg);
-        goto exit;
-    }
-    method = _obj_getProp(obj, methodName);
-    if (NULL != method) {
+    aMethod = obj_getArg(obj, methodName);
+    if (NULL != aMethod) {
+        aMethod = arg_copy_noalloc(aMethod, arg_reg);
         goto exit;
     }
+    aMethod = _obj_getProp(obj, methodName);
 exit:
-    return method;
+    return aMethod;
 }
 
 Arg* obj_getMethodArg(PikaObj* obj, char* methodPath) {
@@ -720,6 +717,9 @@ PikaObj* methodArg_getHostObj(Arg* method_arg) {
 }
 
 int methodArg_setHostObj(Arg* method_arg, PikaObj* host_obj) {
+    if (arg_getType(method_arg) != ARG_TYPE_METHOD_OBJECT) {
+        return -1;
+    }
     MethodProp* prop = (MethodProp*)arg_getContent(method_arg);
     if (prop->host_obj == NULL) {
         prop->host_obj = host_obj;

+ 31 - 34
src/PikaVM.c

@@ -838,8 +838,8 @@ static Arg* _proxy_getattr(PikaObj* host, char* name) {
 static Arg* VM_instruction_handler_REF(PikaObj* self,
                                        VMState* vm,
                                        char* data,
-                                       Arg* arg_ret_reg) {
-    PikaObj* host_obj = NULL;
+                                       Arg* aRetReg) {
+    PikaObj* oHost = NULL;
     char* arg_path = data;
     char* arg_name = strPointToLastToken(arg_path, '.');
     PIKA_BOOL is_temp = PIKA_FALSE;
@@ -847,98 +847,95 @@ static Arg* VM_instruction_handler_REF(PikaObj* self,
     switch (data[0]) {
         case 'T':
             if (strEqu(arg_path, (char*)"True")) {
-                return arg_setBool(arg_ret_reg, "", PIKA_TRUE);
+                return arg_setBool(aRetReg, "", PIKA_TRUE);
             }
             break;
         case 'F':
             if (strEqu(arg_path, (char*)"False")) {
-                return arg_setBool(arg_ret_reg, "", PIKA_FALSE);
+                return arg_setBool(aRetReg, "", PIKA_FALSE);
             }
             break;
         case 'N':
             if (strEqu(arg_path, (char*)"None")) {
-                return arg_setNull(arg_ret_reg);
+                return arg_setNull(aRetReg);
             }
             break;
         case 'R':
             if (strEqu(arg_path, (char*)"RuntimeError")) {
-                return arg_setInt(arg_ret_reg, "", PIKA_RES_ERR_RUNTIME_ERROR);
+                return arg_setInt(aRetReg, "", PIKA_RES_ERR_RUNTIME_ERROR);
             }
             break;
     }
 
-    Arg* res = NULL;
+    Arg* aRes = NULL;
     if (arg_path[0] == '.') {
         /* find host from stack */
         Arg* host_arg = stack_popArg_alloc(&(vm->stack));
         if (argType_isObject(arg_getType(host_arg))) {
-            host_obj = arg_getPtr(host_arg);
-            res = arg_copy_noalloc(obj_getArg(host_obj, arg_path + 1),
-                                   arg_ret_reg);
+            oHost = arg_getPtr(host_arg);
+            aRes = arg_copy_noalloc(obj_getArg(oHost, arg_path + 1), aRetReg);
         }
         arg_deinit(host_arg);
         goto exit;
     }
 
     /* find in local list first */
-    if (NULL == host_obj) {
-        host_obj = obj_getHostObjWithIsTemp(vm->locals, arg_path, &is_temp);
+    if (NULL == oHost) {
+        oHost = obj_getHostObjWithIsTemp(vm->locals, arg_path, &is_temp);
     }
 
     /* find in global list */
-    if (NULL == host_obj) {
-        host_obj = obj_getHostObjWithIsTemp(vm->globals, arg_path, &is_temp);
+    if (NULL == oHost) {
+        oHost = obj_getHostObjWithIsTemp(vm->globals, arg_path, &is_temp);
     }
 
     /* error cannot found host_object */
-    if (NULL == host_obj) {
+    if (NULL == oHost) {
         goto exit;
     }
 
     /* proxy */
-    if (NULL == res) {
-        res = _proxy_getattribute(host_obj, arg_name);
+    if (NULL == aRes) {
+        aRes = _proxy_getattribute(oHost, arg_name);
     }
 
     /* find res in host */
-    if (NULL == res) {
-        res = args_getArg(host_obj->list, arg_name);
+    if (NULL == aRes) {
+        aRes = args_getArg(oHost->list, arg_name);
     }
 
     /* find res in host prop */
-    if (NULL == res) {
-        res = _obj_getProp(host_obj, arg_name);
+    if (NULL == aRes) {
+        aRes = _obj_getProp(oHost, arg_name);
     }
 
     /* find res in globlas */
-    if (NULL == res) {
-        res = args_getArg(vm->globals->list, arg_name);
+    if (NULL == aRes) {
+        aRes = args_getArg(vm->globals->list, arg_name);
     }
 
     /* find res in globals prop */
-    if (NULL == res) {
-        res = _obj_getProp(vm->globals, arg_name);
+    if (NULL == aRes) {
+        aRes = _obj_getProp(vm->globals, arg_name);
     }
 
     /* proxy */
-    if (NULL == res) {
-        res = _proxy_getattr(host_obj, arg_name);
+    if (NULL == aRes) {
+        aRes = _proxy_getattr(oHost, arg_name);
     }
 exit:
-    if (NULL == res) {
+    if (NULL == aRes) {
         VMState_setErrorCode(vm, PIKA_RES_ERR_ARG_NO_FOUND);
         pika_platform_printf("NameError: name '%s' is not defined\r\n",
                              arg_path);
     } else {
-        if (arg_getType(res) == ARG_TYPE_METHOD_OBJECT) {
-            methodArg_setHostObj(res, host_obj);
-        }
-        res = arg_copy_noalloc(res, arg_ret_reg);
+        methodArg_setHostObj(aRes, oHost);
+        aRes = arg_copy_noalloc(aRes, aRetReg);
     }
     if (is_temp) {
-        obj_GC(host_obj);
+        obj_GC(oHost);
     }
-    return res;
+    return aRes;
 }
 
 static Arg* VM_instruction_handler_GER(PikaObj* self,

+ 33 - 16
test/VM-test.cpp

@@ -2648,7 +2648,7 @@ TEST(vm, run_file) {
     EXPECT_EQ(pikaMemNow(), 0);
 }
 
-TEST(vm, bool_){
+TEST(vm, bool_) {
     PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain);
     obj_run(pikaMain, "print(True)\n");
     obj_deinit(pikaMain);
@@ -2656,27 +2656,44 @@ TEST(vm, bool_){
     EXPECT_EQ(pikaMemNow(), 0);
 }
 
-TEST(vm, method_cb){
+TEST(vm, method_cb) {
     PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain);
-    obj_run(pikaMain, 
-    "class Test:\n"
-    "    _cb = None\n"
-    "    def callback(self):\n"
-    "        print('test')\n"
-    "    def addcb(self, cb):\n"
-    "        self._cb = cb\n"
-    "    def runcb(self):\n"
-    "        self._cb()\n"
-    "    def __init__(self):\n"
-    "        self.addcb(self.callback)\n"
-    "t = Test()\n"
-    "t.runcb()"
-    );
+    obj_run(pikaMain,
+            "class Test:\n"
+            "    _cb = None\n"
+            "    def callback(self):\n"
+            "        print('test')\n"
+            "    def addcb(self, cb):\n"
+            "        self._cb = cb\n"
+            "    def runcb(self):\n"
+            "        self._cb()\n"
+            "    def __init__(self):\n"
+            "        self.addcb(self.callback)\n"
+            "t = Test()\n"
+            "t.runcb()");
     obj_deinit(pikaMain);
     EXPECT_STREQ(log_buff[0], "test\r\n");
     EXPECT_EQ(pikaMemNow(), 0);
 }
 
+TEST(vm, class_getattr) {
+    /* init */
+    pikaMemInfo.heapUsedMax = 0;
+    PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain);
+    extern unsigned char pikaModules_py_a[];
+    obj_linkLibrary(pikaMain, pikaModules_py_a);
+    /* run */
+    __platform_printf("BEGIN\r\n");
+    pikaVM_runSingleFile(pikaMain, "test/python/callback/class_getattr.py");
+    /* collect */
+    /* assert */
+    EXPECT_STREQ(log_buff[0], "2\r\n");
+    EXPECT_STREQ(log_buff[1], "1\r\n");
+    /* deinit */
+    obj_deinit(pikaMain);
+    EXPECT_EQ(pikaMemNow(), 0);
+}
+
 #endif
 
 TEST_END

+ 6 - 0
test/compile-test.cpp

@@ -732,4 +732,10 @@ TEST(compiler, prime_100) {
     EXPECT_EQ(pikaMemNow(), 0);
 }
 
+TEST(compiler, getattr_fn) {
+    char* lines = "@res = @obj.@name\n";
+    Parser_linesToArray(lines);
+    EXPECT_EQ(pikaMemNow(), 0);
+}
+
 TEST_END

+ 1 - 1
test/python/_thread/thread_self.py

@@ -15,4 +15,4 @@ class Test:
 
 test = Test()
 while test._val != 3:
-    time.sleep(0.5)
+    time.sleep(0.1)

+ 13 - 0
test/python/callback/class_getattr.py

@@ -0,0 +1,13 @@
+
+class Test:
+    val = 1
+
+    def cb(self):
+        print(self.val)
+        self.val += 1
+
+
+t = Test()
+fn = getattr(t, 'cb')
+fn()
+print(t.val)