Procházet zdrojové kódy

add weakref

add PikaUI test

test PikauI_core passed

save host_obj on methodArg

support save host_obj for method
lyon před 3 roky
rodič
revize
994bb3bdc5

+ 1 - 0
examples/Callback/test2.py

@@ -30,6 +30,7 @@ class Test():
         for func in funcs:
             demo.func = func 
             demo.func()
+            func()
 
 test = Test()
 test.funcs_test()

+ 11 - 0
package/weakref/weakref.c

@@ -0,0 +1,11 @@
+#include "weakref.h"
+
+Arg* weakref_ref(PikaObj* self, Arg* obj) {
+    if (argType_isObject(arg_getType(obj))) {
+        Arg* ret = arg_copy(obj);
+        obj_refcntDec((PikaObj*)arg_getPtr(ret));
+        arg_setIsWeakRef(ret, PIKA_TRUE);
+        return ret;
+    }
+    return NULL;
+}

+ 2 - 0
package/weakref/weakref.pyi

@@ -0,0 +1,2 @@
+
+def ref(obj: any) -> any: ...

+ 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=modbus.rtu_master"
+                "--gtest_filter=vm.cb_2"
             ],
             "stopAtEntry": false,
             "cwd": "${workspaceFolder}",

+ 1 - 2
port/linux/package/pikascript/main.py

@@ -6,8 +6,7 @@ import cb_test
 import configparser, network
 import test_module1, test_cmodule, test_module4, import_test
 import hashlib, hmac, aes, base64, time
-import _thread
-import PikaUI as ui
+import _thread, weakref
 
 mem = PikaStdLib.MemChecker()
 print('hello pikascript!')

+ 11 - 0
port/linux/package/pikascript/pikascript-lib/weakref/weakref.c

@@ -0,0 +1,11 @@
+#include "weakref.h"
+
+Arg* weakref_ref(PikaObj* self, Arg* obj) {
+    if (argType_isObject(arg_getType(obj))) {
+        Arg* ret = arg_copy(obj);
+        obj_refcntDec((PikaObj*)arg_getPtr(ret));
+        arg_setIsWeakRef(ret, PIKA_TRUE);
+        return ret;
+    }
+    return NULL;
+}

+ 2 - 0
port/linux/package/pikascript/weakref.pyi

@@ -0,0 +1,2 @@
+
+def ref(obj: any) -> any: ...

+ 28 - 3
src/PikaObj.c

@@ -113,6 +113,15 @@ static int32_t obj_deinit_no_del(PikaObj* self) {
     return 0;
 }
 
+int obj_GC(PikaObj* self) {
+    obj_refcntDec(self);
+    int ref_cnt = obj_refcntNow(self);
+    if (ref_cnt <= 0) {
+        obj_deinit(self);
+    }
+    return 0;
+}
+
 int32_t obj_deinit(PikaObj* self) {
     Arg* del = obj_getMethodArg(self, "__del__");
     if (NULL != del) {
@@ -675,9 +684,9 @@ Method methodArg_getPtr(Arg* method_arg) {
 }
 
 char* methodArg_getTypeList(Arg* method_arg, char* buffs, size_t size) {
-    MethodProp* method_store = (MethodProp*)arg_getContent(method_arg);
-    if (NULL != method_store->type_list) {
-        return strcpy(buffs, method_store->type_list);
+    MethodProp* prop = (MethodProp*)arg_getContent(method_arg);
+    if (NULL != prop->type_list) {
+        return strcpy(buffs, prop->type_list);
     }
     char* method_dec = methodArg_getDec(method_arg);
     pika_assert(strGetSize(method_dec) <= size);
@@ -692,6 +701,21 @@ char* methodArg_getTypeList(Arg* method_arg, char* buffs, size_t size) {
     return res;
 }
 
+PikaObj* methodArg_getHostObj(Arg* method_arg) {
+    MethodProp* prop = (MethodProp*)arg_getContent(method_arg);
+    return prop->host_obj;
+}
+
+int methodArg_setHostObj(Arg* method_arg, PikaObj* host_obj) {
+    MethodProp* prop = (MethodProp*)arg_getContent(method_arg);
+    if (prop->host_obj == NULL) {
+        prop->host_obj = host_obj;
+        // obj_refcntInc(host_obj);
+        return 0;
+    }
+    return 0;
+}
+
 char* methodArg_getName(Arg* method_arg, char* buffs, size_t size) {
     MethodProp* method_store = (MethodProp*)arg_getContent(method_arg);
     if (NULL != method_store->name) {
@@ -764,6 +788,7 @@ static void obj_saveMethodInfo(PikaObj* self, MethodInfo* method_info) {
         .bytecode_frame = method_info->bytecode_frame,
         .def_context = method_info->def_context,
         .declareation = method_info->dec,  // const
+        .host_obj = NULL,
     };
     char* name = method_info->name;
     if (NULL == method_info->name) {

+ 4 - 0
src/PikaObj.h

@@ -135,6 +135,7 @@ typedef struct MethodProp {
     char* name;
     ByteCodeFrame* bytecode_frame;
     PikaObj* def_context;
+    PikaObj* host_obj;
     char* declareation;
 } MethodProp;
 
@@ -151,6 +152,7 @@ typedef PikaObj PikaMaker;
 
 /* operation */
 int32_t obj_deinit(PikaObj* self);
+int obj_GC(PikaObj* self);
 int32_t obj_init(PikaObj* self, Args* args);
 int32_t obj_update(PikaObj* self);
 int32_t obj_enable(PikaObj* self);
@@ -255,6 +257,8 @@ void method_returnArg(Args* args, Arg* arg);
 char* methodArg_getDec(Arg* method_arg);
 char* methodArg_getTypeList(Arg* method_arg, char* buffs, size_t size);
 char* methodArg_getName(Arg* method_arg, char* buffs, size_t size);
+int methodArg_setHostObj(Arg* method_arg, PikaObj* host_obj);
+PikaObj* methodArg_getHostObj(Arg* method_arg);
 ByteCodeFrame* methodArg_getBytecodeFrame(Arg* method_arg);
 Method methodArg_getPtr(Arg* method_arg);
 

+ 25 - 18
src/PikaVM.c

@@ -757,7 +757,7 @@ static Arg* VM_instruction_handler_REF(PikaObj* self,
                                        VMState* vm,
                                        char* data,
                                        Arg* arg_ret_reg) {
-    PikaObj* host_object = NULL;
+    PikaObj* host_obj = NULL;
     char* arg_path = data;
     char* arg_name = strPointToLastToken(arg_path, '.');
     PIKA_BOOL is_temp = PIKA_FALSE;
@@ -788,44 +788,44 @@ static Arg* VM_instruction_handler_REF(PikaObj* self,
     Arg* res = NULL;
     if (arg_path[0] == '.') {
         /* find host from stack */
-        Arg* host_obj = stack_popArg_alloc(&(vm->stack));
-        if (argType_isObject(arg_getType(host_obj))) {
-            host_object = arg_getPtr(host_obj);
-            res = arg_copy_noalloc(obj_getArg(host_object, arg_path + 1),
+        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);
         }
-        arg_deinit(host_obj);
+        arg_deinit(host_arg);
         goto exit;
     }
 
     /* find in local list first */
-    if (NULL == host_object) {
-        host_object = obj_getHostObjWithIsTemp(vm->locals, arg_path, &is_temp);
+    if (NULL == host_obj) {
+        host_obj = obj_getHostObjWithIsTemp(vm->locals, arg_path, &is_temp);
     }
 
     /* find in global list */
-    if (NULL == host_object) {
-        host_object = obj_getHostObjWithIsTemp(vm->globals, arg_path, &is_temp);
+    if (NULL == host_obj) {
+        host_obj = obj_getHostObjWithIsTemp(vm->globals, arg_path, &is_temp);
     }
 
     /* error cannot found host_object */
-    if (NULL == host_object) {
+    if (NULL == host_obj) {
         goto exit;
     }
 
     /* proxy */
     if (NULL == res) {
-        res = _proxy_getattribute(host_object, arg_name);
+        res = _proxy_getattribute(host_obj, arg_name);
     }
 
     /* find res in host */
     if (NULL == res) {
-        res = args_getArg(host_object->list, arg_name);
+        res = args_getArg(host_obj->list, arg_name);
     }
 
     /* find res in host prop */
     if (NULL == res) {
-        res = _obj_getProp(host_object, arg_name);
+        res = _obj_getProp(host_obj, arg_name);
     }
 
     /* find res in globlas */
@@ -840,7 +840,7 @@ static Arg* VM_instruction_handler_REF(PikaObj* self,
 
     /* proxy */
     if (NULL == res) {
-        res = _proxy_getattr(host_object, arg_name);
+        res = _proxy_getattr(host_obj, arg_name);
     }
 exit:
     if (NULL == res) {
@@ -848,10 +848,13 @@ exit:
         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);
     }
     if (is_temp) {
-        obj_deinit(host_object);
+        obj_GC(host_obj);
     }
     return res;
 }
@@ -1390,7 +1393,11 @@ static int VMState_loadArgsFromMethodArg(VMState* vm,
 
     /* load 'self' as the first arg when call object method */
     if (f.method_type == ARG_TYPE_METHOD_OBJECT) {
-        Arg* call_arg = arg_setRef(NULL, "self", method_host_obj);
+        PikaObj* method_self = methodArg_getHostObj(method_arg);
+        if (NULL == method_self) {
+            method_self = method_host_obj;
+        }
+        Arg* call_arg = arg_setRef(NULL, "self", method_self);
         pika_assert(call_arg != NULL);
         argv[argc++] = call_arg;
     }
@@ -1813,7 +1820,7 @@ exit:
     }
     if (NULL != method_host && is_temp) {
         /* class method */
-        obj_deinit(method_host);
+        obj_GC(method_host);
     }
 
     return return_arg;

+ 22 - 13
src/dataArg.c

@@ -452,15 +452,24 @@ Arg* New_arg(void* voidPointer) {
     return NULL;
 }
 
+static void _arg_refcnt_fix(Arg* self) {
+    ArgType arg_type = arg_getType(self);
+    if (ARG_TYPE_OBJECT == arg_type) {
+        obj_refcntInc((PikaObj*)arg_getPtr(self));
+    }
+    // if (ARG_TYPE_METHOD_OBJECT == arg_type) {
+    //     if (NULL != methodArg_getHostObj(self)) {
+    //         obj_refcntInc((PikaObj*)arg_getPtr(self));
+    //     }
+    // }
+}
+
 Arg* arg_copy(Arg* arg_src) {
     if (NULL == arg_src) {
         return NULL;
     }
     pika_assert(arg_src->flag < ARG_FLAG_MAX);
-    ArgType arg_type = arg_getType(arg_src);
-    if (ARG_TYPE_OBJECT == arg_type) {
-        obj_refcntInc((PikaObj*)arg_getPtr(arg_src));
-    }
+    _arg_refcnt_fix(arg_src);
     Arg* arg_dict = New_arg(NULL);
     arg_dict = arg_setContent(arg_dict, arg_getContent(arg_src),
                               arg_getContentSize(arg_src));
@@ -482,10 +491,7 @@ Arg* arg_copy_noalloc(Arg* arg_src, Arg* arg_dict) {
     if (arg_getSize(arg_src) > arg_getSize(arg_dict)) {
         return arg_copy(arg_src);
     }
-    ArgType arg_type = arg_getType(arg_src);
-    if (ARG_TYPE_OBJECT == arg_type) {
-        obj_refcntInc((PikaObj*)arg_getPtr(arg_src));
-    }
+    _arg_refcnt_fix(arg_src);
     arg_setSerialized(arg_dict, PIKA_FALSE);
     arg_dict = arg_setContent(arg_dict, arg_getContent(arg_src),
                               arg_getContentSize(arg_src));
@@ -533,6 +539,7 @@ void* arg_getHeapStruct(Arg* self) {
     return arg_getContent(self) + sizeof(void*);
 }
 
+
 void arg_deinitHeap(Arg* self) {
     if (arg_getIsWeakRef(self)) {
         return;
@@ -549,13 +556,15 @@ void arg_deinitHeap(Arg* self) {
     /* deinit sub object */
     if (ARG_TYPE_OBJECT == type) {
         PikaObj* subObj = arg_getPtr(self);
-        obj_refcntDec(subObj);
-        int ref_cnt = obj_refcntNow(subObj);
-        if (ref_cnt <= 0) {
-            obj_deinit(subObj);
-        }
+        obj_GC(subObj);
         return;
     }
+    // if (ARG_TYPE_METHOD_OBJECT == type) {
+    //     PikaObj* hostObj = methodArg_getHostObj(self);
+    //     if (NULL != hostObj) {
+    //         obj_GC(hostObj);
+    //     }
+    // }
 }
 
 /* load file as byte array */

+ 21 - 26
test/VM-test.cpp

@@ -1355,15 +1355,33 @@ TEST(vm, cb_2) {
     pikaVM_runSingleFile(pikaMain, "../../examples/Callback/test2.py");
     /* collect */
     /* assert */
-    EXPECT_STREQ(log_buff[4], "__init__\r\n");
-    EXPECT_STREQ(log_buff[2], "a\r\n");
-    EXPECT_STREQ(log_buff[1], "b\r\n");
+    EXPECT_STREQ(log_buff[6], "__init__\r\n");
+    EXPECT_STREQ(log_buff[5], "a\r\n");
+    EXPECT_STREQ(log_buff[4], "a\r\n");
+    EXPECT_STREQ(log_buff[3], "b\r\n");
+    EXPECT_STREQ(log_buff[2], "b\r\n");
+    EXPECT_STREQ(log_buff[1], "ppp\r\n");
     EXPECT_STREQ(log_buff[0], "ppp\r\n");
     /* deinit */
     obj_deinit(pikaMain);
     EXPECT_EQ(pikaMemNow(), 0);
 }
 
+TEST(vm, cb_3) {
+    /* 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/test3.py");
+    /* collect */
+    /* deinit */
+    obj_deinit(pikaMain);
+    EXPECT_EQ(pikaMemNow(), 0);
+}
+
 #endif
 
 #if !PIKA_NANO_ENABLE
@@ -2630,29 +2648,6 @@ TEST(vm, run_file) {
     EXPECT_EQ(pikaMemNow(), 0);
 }
 
-// TEST(vm, ui_page) {
-//     /* 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");
-//     obj_run(pikaMain,
-//             "import PikaUI as ui\n"
-//             "ui.Page().add(\n"
-//             "    ui.Widget(\n"
-//             "    ).add(\n"
-//             "        ui.Text()\n"
-//             "    ),\n"
-//             ")\n");
-//     /* collect */
-//     /* assert */
-//     /* deinit */
-//     obj_deinit(pikaMain);
-//     EXPECT_EQ(pikaMemNow(), 0);
-// }
-
 #endif
 
 TEST_END

+ 21 - 0
test/pikaui-test.cpp

@@ -0,0 +1,21 @@
+#include "test_common.h"
+TEST_START
+#if !PIKA_NANO_ENABLE
+
+TEST(pikaui, page) {
+    /* init */
+    pikaMemInfo.heapUsedMax = 0;
+    PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain);
+    /* run */
+    __platform_printf("BEGIN\r\n");
+    pikaVM_runFile(pikaMain, "test/python/PikaUI/test_page.py");
+    /* collect */
+    /* assert */
+    /* deinit */
+    obj_deinit(pikaMain);
+    EXPECT_EQ(pikaMemNow(), 0);
+}
+
+
+#endif
+TEST_END

+ 2 - 2
port/linux/package/pikascript/PikaUI.py → test/python/PikaUI/PikaUI.py

@@ -1,7 +1,7 @@
 import PikaUI_core as core
-# import pika_lvgl
+import textgui
 
-# core.set_backend(pika_lvgl)
+core.set_backend(textgui)
 
 class Widget(core.Widget):
     pass

+ 20 - 9
port/linux/package/pikascript/PikaUI_core.py → test/python/PikaUI/PikaUI_core.py

@@ -1,13 +1,17 @@
+import weakref
 # class ALIGN(_backend.ALIGN): (vm not pass)
 #     pass
 
+
 class _ALIGN:
     CENTER = 0
     TOP_MID = 1
 
+
 ALIGN = _ALIGN
 _backend = None
 
+
 def set_backend(backend):
     global _backend
     global ALIGN
@@ -15,7 +19,8 @@ def set_backend(backend):
     _backend = backend
     ALIGN = _backend.ALIGN
     page = _Page()
-    page.parent = page
+    page._setPerent(page)
+    page.isroot = True
     page.backend = _backend.scr_act()
 
 
@@ -27,6 +32,7 @@ class Widget:
     parent = None
     align = None
     text = None
+    isroot = False
     _label = None
     _child = []
 
@@ -34,32 +40,34 @@ class Widget:
                  width=100,
                  height=100,
                  pos=None,
-                 parent=None,
                  text=None,
                  align=ALIGN.TOP_MID):
         self.width = width
         self.height = height
         self.pos = pos
-        self.parent = parent
         self.align = align
         self.text = text
 
     def _setPerent(self, parent):
-        self.parent = parent
+        self.parent = weakref.ref(parent)
 
     def update(self):
         if self.parent is None:
+            print('self.parent is None')
             return
 
         if self.parent.backend is None:
+            print('self.parent.backend is None')
             return
 
         if self.backend is None:
             self.backend = self._createBackend(self.parent)
 
-        self._updateAlign(self.align)
-        self._updateAttr(self.width, self.height, self.pos)
-        self._updateText(self.text)
+        if not self.isroot:
+            self._updateAlign(self.align)
+            self._updateAttr(self.width, self.height, self.pos)
+            self._updateText(self.text)
+
         for c in self._child:
             c.update()
 
@@ -93,7 +101,8 @@ class Widget:
 
 class _Page(Widget):
     def _createBackend(self, parent: Widget):
-        return _backend.scr_act() 
+        return _backend.scr_act()
+
 
 class Button(Widget):
     def _createBackend(self, parent: Widget):
@@ -107,7 +116,9 @@ class Text(Widget):
     def _updateText(self, text):
         self.backend.set_text(text)
 
+
 page = _Page()
 
+
 def Page():
-    return page
+    return page

+ 0 - 0
test/python/PikaUI/pikascript-api/keep


+ 8 - 0
test/python/PikaUI/test_page.py

@@ -0,0 +1,8 @@
+import PikaUI as ui
+
+ui.Page().add(
+    ui.Widget(
+    ).add(
+        ui.Text()
+    ),
+).update()

+ 33 - 0
test/python/PikaUI/textgui.py

@@ -0,0 +1,33 @@
+
+class lv_obj:
+    name = "widget"
+
+    def __init__(self, parent):
+        if parent == None:
+            name = 'None'
+        else:
+            name = parent.name
+        print('%s.__init__(%s)' % (self.name, name))
+
+    def align(self, align, posx, posy):
+        print('%s.align(%d, %d, %d)' % (self.name, align, posx, posy))
+
+    def set_width(self, width):
+        print('%s.set_wdith(%d)' % (self.name, width))
+
+    def set_height(self, height):
+        print('%s.set_height(%d)' % (self.name, height))
+    
+    def set_text(self, text):
+        print('%s.set_text(%s)' % (self.name, text))
+
+class Screen:
+    name = "screen"
+
+_screen = Screen(None)
+
+class label(lv_obj):
+    name = "label"
+
+def scr_act():
+    return _screen

+ 8 - 0
test/python/callback/test3.py

@@ -0,0 +1,8 @@
+
+class Test:
+    def foo(self):
+        print('hello')
+
+t = Test()
+fo = t.foo
+t.fn = fo