Преглед изворни кода

fix `py_name2ref`

Update vm.c

backup
blueloveTH пре 8 месеци
родитељ
комит
4fd47072fc

+ 1 - 0
include/pocketpy/interpreter/typeinfo.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "pocketpy/pocketpy.h"
+#include "pocketpy/common/vector.h"
 #include "pocketpy/objects/object.h"
 
 #define PK_MAX_CHUNK_LENGTH 256

+ 3 - 9
include/pocketpy/interpreter/vm.h

@@ -3,6 +3,7 @@
 #include "pocketpy/common/memorypool.h"
 #include "pocketpy/common/name.h"
 #include "pocketpy/objects/codeobject.h"
+#include "pocketpy/objects/bintree.h"
 #include "pocketpy/pocketpy.h"
 #include "pocketpy/interpreter/heap.h"
 #include "pocketpy/interpreter/frame.h"
@@ -30,7 +31,7 @@ typedef struct WatchdogInfo {
 typedef struct VM {
     py_Frame* top_frame;
 
-    ModuleDict modules;
+    BinTree modules;
     TypeList types;
 
     py_TValue builtins;  // builtins module
@@ -49,7 +50,7 @@ typedef struct VM {
     py_TValue reg[8];  // users' registers
     void* ctx;         // user-defined context
 
-    NameDict cached_names;
+    BinTree cached_names;
 
     py_StackRef curr_class;
     py_StackRef curr_decl_based_function;
@@ -76,13 +77,6 @@ bool pk__parse_int_slice(py_Ref slice,
                          int* restrict step);
 bool pk__normalize_index(int* index, int length);
 
-#define pk__mark_value(val)                                                                        \
-    if((val)->is_ptr && !(val)->_obj->gc_marked) {                                                 \
-        PyObject* obj = (val)->_obj;                                                               \
-        obj->gc_marked = true;                                                                     \
-        c11_vector__push(PyObject*, p_stack, obj);                                                 \
-    }
-
 bool pk__object_new(int argc, py_Ref argv);
 py_TypeInfo* pk__type_info(py_Type type);
 

+ 25 - 0
include/pocketpy/objects/bintree.h

@@ -0,0 +1,25 @@
+#pragma once
+
+#include "pocketpy/objects/base.h"
+#include "pocketpy/common/vector.h"
+#include "pocketpy/pocketpy.h"
+
+typedef struct BinTreeConfig {
+    int (*f_cmp)(void* lhs, void* rhs);
+    bool need_free_key;
+} BinTreeConfig;
+
+typedef struct BinTree {
+    void* key;
+    py_TValue value;
+    const BinTreeConfig* config;
+    struct BinTree* left;
+    struct BinTree* right;
+} BinTree;
+
+void BinTree__ctor(BinTree* self, void* key, py_Ref value, const BinTreeConfig* config);
+void BinTree__dtor(BinTree* self);
+void BinTree__set(BinTree* self, void* key, py_Ref value);
+py_Ref BinTree__try_get(BinTree* self, void* key);
+bool BinTree__contains(BinTree* self, void* key);
+void BinTree__apply_mark(BinTree* self, c11_vector* p_stack);

+ 0 - 18
include/pocketpy/objects/namedict.h

@@ -1,26 +1,8 @@
 #pragma once
 
-#include "pocketpy/common/vector.h"
 #include "pocketpy/objects/base.h"
 #include "pocketpy/pocketpy.h"
 
-/* A simple binary tree for storing modules. */
-typedef struct ModuleDict {
-    char path[PK_MAX_MODULE_PATH_LEN + 1];
-    py_TValue module;
-    struct ModuleDict* left;
-    struct ModuleDict* right;
-} ModuleDict;
-
-void ModuleDict__ctor(ModuleDict* self, const char* path, py_TValue module);
-void ModuleDict__dtor(ModuleDict* self);
-void ModuleDict__set(ModuleDict* self, const char* key, py_TValue val);
-py_TValue* ModuleDict__try_get(ModuleDict* self, const char* path);
-bool ModuleDict__contains(ModuleDict* self, const char* path);
-void ModuleDict__apply_mark(ModuleDict* self, c11_vector* p_stack);
-
-/////////////////// NameDict ///////////////////
-
 typedef struct NameDict_KV {
     py_Name key;
     py_TValue value;

+ 7 - 0
include/pocketpy/objects/object.h

@@ -25,3 +25,10 @@ void* PyObject__userdata(PyObject* self);
 
 void PyObject__dtor(PyObject* self);
 
+
+#define pk__mark_value(val)                                                                        \
+    if((val)->is_ptr && !(val)->_obj->gc_marked) {                                                 \
+        PyObject* obj = (val)->_obj;                                                               \
+        obj->gc_marked = true;                                                                     \
+        c11_vector__push(PyObject*, p_stack, obj);                                                 \
+    }

+ 1 - 1
include/pocketpy/pocketpy.h

@@ -245,7 +245,7 @@ PK_API py_Name py_name(const char*);
 /// Convert a name to a null-terminated string.
 PK_API const char* py_name2str(py_Name);
 /// Convert a name to a python `str` object with cache.
-PK_API py_ItemRef py_name2ref(py_Name);
+PK_API py_GlobalRef py_name2ref(py_Name);
 /// Convert a `c11_sv` to a name.
 PK_API py_Name py_namev(c11_sv);
 /// Convert a name to a `c11_sv`.

+ 33 - 11
src/interpreter/vm.c

@@ -66,10 +66,24 @@ static void py_TypeInfo__ctor(py_TypeInfo* self,
     c11_vector__ctor(&self->ordered_attrs, sizeof(py_Name));
 }
 
+static int BinTree__cmp_cstr(void* lhs, void* rhs) {
+    const char* l = (const char*)lhs;
+    const char* r = (const char*)rhs;
+    return strcmp(l, r);
+}
+
+static int BinTree__cmp_voidp(void* lhs, void* rhs) {
+    return lhs < rhs ? -1 : (lhs > rhs ? 1 : 0);
+}
+
 void VM__ctor(VM* self) {
     self->top_frame = NULL;
 
-    ModuleDict__ctor(&self->modules, "", *py_NIL());
+    static const BinTreeConfig modules_config = {
+        .f_cmp = BinTree__cmp_cstr,
+        .need_free_key = true,
+    };
+    BinTree__ctor(&self->modules, c11_strdup(""), py_NIL(), &modules_config);
     TypeList__ctor(&self->types);
 
     self->builtins = *py_NIL();
@@ -99,7 +113,12 @@ void VM__ctor(VM* self) {
 
     ManagedHeap__ctor(&self->heap);
     ValueStack__ctor(&self->stack);
-    NameDict__ctor(&self->cached_names, PK_INST_ATTR_LOAD_FACTOR);
+
+    static const BinTreeConfig cached_names_config = {
+        .f_cmp = BinTree__cmp_voidp,
+        .need_free_key = false,
+    };
+    BinTree__ctor(&self->cached_names, NULL, py_NIL(), &cached_names_config);
 
     /* Init Builtin Types */
     // 0: unused
@@ -273,11 +292,11 @@ void VM__dtor(VM* self) {
     // clear frames
     while(self->top_frame)
         VM__pop_frame(self);
-    ModuleDict__dtor(&self->modules);
+    BinTree__dtor(&self->modules);
     TypeList__dtor(&self->types);
     FixedMemoryPool__dtor(&self->pool_frame);
     ValueStack__dtor(&self->stack);
-    NameDict__dtor(&self->cached_names);
+    BinTree__dtor(&self->cached_names);
 }
 
 void VM__push_frame(VM* self, py_Frame* frame) {
@@ -653,7 +672,9 @@ void ManagedHeap__mark(ManagedHeap* self) {
         pk__mark_value(p);
     }
     // mark modules
-    ModuleDict__apply_mark(&vm->modules, p_stack);
+    BinTree__apply_mark(&vm->modules, p_stack);
+    // mark cached names
+    BinTree__apply_mark(&vm->cached_names, p_stack);
     // mark types
     int types_length = vm->types.length;
     // 0-th type is placeholder
@@ -849,12 +870,13 @@ int py_replinput(char* buf, int max_size) {
 
 py_Ref py_name2ref(py_Name name) {
     assert(name != NULL);
-    NameDict* d = &pk_current_vm->cached_names;
-    py_Ref res = NameDict__try_get(d, name);
+    BinTree* d = &pk_current_vm->cached_names;
+    py_Ref res = BinTree__try_get(d, name);
     if(res != NULL) return res;
     // not found, create a new one
-    py_TValue tmp;
-    py_newstrv(&tmp, py_name2sv(name));
-    NameDict__set(d, name, &tmp);
-    return NameDict__try_get(d, name);
+    py_StackRef tmp = py_pushtmp();
+    py_newstrv(tmp, py_name2sv(name));
+    BinTree__set(d, name, tmp);
+    py_pop();
+    return BinTree__try_get(d, name);
 }

+ 72 - 0
src/objects/bintree.c

@@ -0,0 +1,72 @@
+#include "pocketpy/objects/bintree.h"
+
+#include "pocketpy/common/vector.h"
+#include "pocketpy/objects/object.h"
+
+void BinTree__ctor(BinTree* self, void* key, py_Ref value, const BinTreeConfig* config) {
+    self->key = key;
+    self->value = *value;
+    self->config = config;
+    self->left = NULL;
+    self->right = NULL;
+}
+
+void BinTree__dtor(BinTree* self) {
+    if(self->config->need_free_key) PK_FREE(self->key);
+    if(self->left) {
+        BinTree__dtor(self->left);
+        PK_FREE(self->left);
+    }
+    if(self->right) {
+        BinTree__dtor(self->right);
+        PK_FREE(self->right);
+    }
+}
+
+void BinTree__set(BinTree* self, void* key, py_Ref value) {
+    int cmp = self->config->f_cmp(key, self->key);
+    if(cmp < 0) {
+        if(self->left) {
+            BinTree__set(self->left, key, value);
+        } else {
+            self->left = PK_MALLOC(sizeof(BinTree));
+            BinTree__ctor(self->left, key, value, self->config);
+        }
+    } else if(cmp > 0) {
+        if(self->right) {
+            BinTree__set(self->right, key, value);
+        } else {
+            self->right = PK_MALLOC(sizeof(BinTree));
+            BinTree__ctor(self->right, key, value, self->config);
+        }
+    } else {
+        self->value = *value;
+    }
+}
+
+py_Ref BinTree__try_get(BinTree* self, void* key) {
+    int cmp = self->config->f_cmp(key, self->key);
+    if(cmp < 0) {
+        if(self->left) {
+            return BinTree__try_get(self->left, key);
+        } else {
+            return NULL;
+        }
+    } else if(cmp > 0) {
+        if(self->right) {
+            return BinTree__try_get(self->right, key);
+        } else {
+            return NULL;
+        }
+    } else {
+        return &self->value;
+    }
+}
+
+bool BinTree__contains(BinTree* self, void* key) { return BinTree__try_get(self, key) != NULL; }
+
+void BinTree__apply_mark(BinTree* self, c11_vector* p_stack) {
+    pk__mark_value(&self->value);
+    if(self->left) BinTree__apply_mark(self->left, p_stack);
+    if(self->right) BinTree__apply_mark(self->right, p_stack);
+}

+ 4 - 87
src/objects/namedict.c

@@ -1,93 +1,10 @@
 #include "pocketpy/objects/namedict.h"
 #include "pocketpy/common/utils.h"
-#include "pocketpy/objects/object.h"
-#include "pocketpy/pocketpy.h"
-#include <stdint.h>
-
-void ModuleDict__ctor(ModuleDict* self, const char* path, py_TValue module) {
-    assert(path != NULL);
-    int length = strlen(path);
-    assert(length <= PK_MAX_MODULE_PATH_LEN);
-    memcpy(self->path, path, length);
-    self->path[length] = '\0';
-    self->module = module;
-    self->left = NULL;
-    self->right = NULL;
-}
-
-void ModuleDict__dtor(ModuleDict* self) {
-    if(self->left) {
-        ModuleDict__dtor(self->left);
-        PK_FREE(self->left);
-    }
-    if(self->right) {
-        ModuleDict__dtor(self->right);
-        PK_FREE(self->right);
-    }
-}
-
-void ModuleDict__set(ModuleDict* self, const char* key, py_TValue val) {
-    assert(key != NULL);
-    int cmp = strcmp(key, self->path);
-    if(cmp < 0) {
-        if(self->left) {
-            ModuleDict__set(self->left, key, val);
-        } else {
-            self->left = PK_MALLOC(sizeof(ModuleDict));
-            ModuleDict__ctor(self->left, key, val);
-        }
-    } else if(cmp > 0) {
-        if(self->right) {
-            ModuleDict__set(self->right, key, val);
-        } else {
-            self->right = PK_MALLOC(sizeof(ModuleDict));
-            ModuleDict__ctor(self->right, key, val);
-        }
-    } else {
-        self->module = val;
-    }
-}
 
-py_TValue* ModuleDict__try_get(ModuleDict* self, const char* path) {
-    assert(path != NULL);
-    int cmp = strcmp(path, self->path);
-    if(cmp < 0) {
-        if(self->left) {
-            return ModuleDict__try_get(self->left, path);
-        } else {
-            return NULL;
-        }
-    } else if(cmp > 0) {
-        if(self->right) {
-            return ModuleDict__try_get(self->right, path);
-        } else {
-            return NULL;
-        }
-    } else {
-        return &self->module;
-    }
-}
-
-bool ModuleDict__contains(ModuleDict* self, const char* path) {
-    assert(path != NULL);
-    return ModuleDict__try_get(self, path) != NULL;
-}
-
-void ModuleDict__apply_mark(ModuleDict* self, c11_vector* p_stack) {
-    if(!py_isnil(&self->module)) {
-        // root node is dummy
-        PyObject* obj = self->module._obj;
-        assert(obj != NULL);
-        if(!obj->gc_marked) {
-            obj->gc_marked = true;
-            c11_vector__push(PyObject*, p_stack, obj);
-        }
-    }
-    if(self->left) ModuleDict__apply_mark(self->left, p_stack);
-    if(self->right) ModuleDict__apply_mark(self->right, p_stack);
-}
-
-/////////////////// NameDict ///////////////////
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
 
 #define HASH_PROBE_1(__k, ok, i)                                                                   \
     ok = false;                                                                                    \

+ 3 - 3
src/public/modules.c

@@ -13,7 +13,7 @@
 
 py_Ref py_getmodule(const char* path) {
     VM* vm = pk_current_vm;
-    return ModuleDict__try_get(&vm->modules, path);
+    return BinTree__try_get(&vm->modules, (void*)path);
 }
 
 py_Ref py_getbuiltin(py_Name name) { return py_getdict(&pk_current_vm->builtins, name); }
@@ -54,12 +54,12 @@ py_Ref py_newmodule(const char* path) {
 
     // we do not allow override in order to avoid memory leak
     // it is because Module objects are not garbage collected
-    bool exists = ModuleDict__contains(&pk_current_vm->modules, path);
+    bool exists = BinTree__contains(&pk_current_vm->modules, (void*)path);
     if(exists) c11__abort("module '%s' already exists", path);
 
     // convert to a weak (const char*)
     path = py_tostr(py_getdict(r0, __path__));
-    ModuleDict__set(&pk_current_vm->modules, path, *r0);
+    BinTree__set(&pk_current_vm->modules, c11_strdup(path), r0);
 
     py_shrink(2);
     return py_getmodule(path);

+ 23 - 0
tests/81_dataclasses.py

@@ -34,3 +34,26 @@ assert d.i == 1
 assert d.j == 2
 assert d.k == 'default'
 assert d.sum() == 3
+
+
+@dataclass
+class PrimaryForceConfig:
+    # 风场图
+    planetary_wind: 'str'
+    local_wind: int
+    # 地壳运动(含地震带/地形生成)
+    geothermal_activity: int
+    # 太阳辐射标量场
+    solar_radiation: int
+    # 水汽场
+    planetary_humidity: int
+
+config = PrimaryForceConfig(
+   planetary_wind = 'default',
+   local_wind = 1,
+   geothermal_activity = 2,
+   solar_radiation = 3,
+   planetary_humidity = 4
+)
+
+assert config.planetary_wind == 'default'