fix py_name2ref

Update vm.c

backup
This commit is contained in:
blueloveTH 2025-06-13 16:49:05 +08:00
parent a7159e5496
commit 4fd47072fc
11 changed files with 172 additions and 129 deletions

View File

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

View File

@ -3,6 +3,7 @@
#include "pocketpy/common/memorypool.h" #include "pocketpy/common/memorypool.h"
#include "pocketpy/common/name.h" #include "pocketpy/common/name.h"
#include "pocketpy/objects/codeobject.h" #include "pocketpy/objects/codeobject.h"
#include "pocketpy/objects/bintree.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
#include "pocketpy/interpreter/heap.h" #include "pocketpy/interpreter/heap.h"
#include "pocketpy/interpreter/frame.h" #include "pocketpy/interpreter/frame.h"
@ -30,7 +31,7 @@ typedef struct WatchdogInfo {
typedef struct VM { typedef struct VM {
py_Frame* top_frame; py_Frame* top_frame;
ModuleDict modules; BinTree modules;
TypeList types; TypeList types;
py_TValue builtins; // builtins module py_TValue builtins; // builtins module
@ -49,7 +50,7 @@ typedef struct VM {
py_TValue reg[8]; // users' registers py_TValue reg[8]; // users' registers
void* ctx; // user-defined context void* ctx; // user-defined context
NameDict cached_names; BinTree cached_names;
py_StackRef curr_class; py_StackRef curr_class;
py_StackRef curr_decl_based_function; py_StackRef curr_decl_based_function;
@ -76,13 +77,6 @@ bool pk__parse_int_slice(py_Ref slice,
int* restrict step); int* restrict step);
bool pk__normalize_index(int* index, int length); 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); bool pk__object_new(int argc, py_Ref argv);
py_TypeInfo* pk__type_info(py_Type type); py_TypeInfo* pk__type_info(py_Type type);

View File

@ -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);

View File

@ -1,26 +1,8 @@
#pragma once #pragma once
#include "pocketpy/common/vector.h"
#include "pocketpy/objects/base.h" #include "pocketpy/objects/base.h"
#include "pocketpy/pocketpy.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 { typedef struct NameDict_KV {
py_Name key; py_Name key;
py_TValue value; py_TValue value;

View File

@ -25,3 +25,10 @@ void* PyObject__userdata(PyObject* self);
void PyObject__dtor(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); \
}

View File

@ -245,7 +245,7 @@ PK_API py_Name py_name(const char*);
/// Convert a name to a null-terminated string. /// Convert a name to a null-terminated string.
PK_API const char* py_name2str(py_Name); PK_API const char* py_name2str(py_Name);
/// Convert a name to a python `str` object with cache. /// 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. /// Convert a `c11_sv` to a name.
PK_API py_Name py_namev(c11_sv); PK_API py_Name py_namev(c11_sv);
/// Convert a name to a `c11_sv`. /// Convert a name to a `c11_sv`.

View File

@ -66,10 +66,24 @@ static void py_TypeInfo__ctor(py_TypeInfo* self,
c11_vector__ctor(&self->ordered_attrs, sizeof(py_Name)); 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) { void VM__ctor(VM* self) {
self->top_frame = NULL; 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); TypeList__ctor(&self->types);
self->builtins = *py_NIL(); self->builtins = *py_NIL();
@ -99,7 +113,12 @@ void VM__ctor(VM* self) {
ManagedHeap__ctor(&self->heap); ManagedHeap__ctor(&self->heap);
ValueStack__ctor(&self->stack); 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 */ /* Init Builtin Types */
// 0: unused // 0: unused
@ -273,11 +292,11 @@ void VM__dtor(VM* self) {
// clear frames // clear frames
while(self->top_frame) while(self->top_frame)
VM__pop_frame(self); VM__pop_frame(self);
ModuleDict__dtor(&self->modules); BinTree__dtor(&self->modules);
TypeList__dtor(&self->types); TypeList__dtor(&self->types);
FixedMemoryPool__dtor(&self->pool_frame); FixedMemoryPool__dtor(&self->pool_frame);
ValueStack__dtor(&self->stack); ValueStack__dtor(&self->stack);
NameDict__dtor(&self->cached_names); BinTree__dtor(&self->cached_names);
} }
void VM__push_frame(VM* self, py_Frame* frame) { void VM__push_frame(VM* self, py_Frame* frame) {
@ -653,7 +672,9 @@ void ManagedHeap__mark(ManagedHeap* self) {
pk__mark_value(p); pk__mark_value(p);
} }
// mark modules // 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 // mark types
int types_length = vm->types.length; int types_length = vm->types.length;
// 0-th type is placeholder // 0-th type is placeholder
@ -849,12 +870,13 @@ int py_replinput(char* buf, int max_size) {
py_Ref py_name2ref(py_Name name) { py_Ref py_name2ref(py_Name name) {
assert(name != NULL); assert(name != NULL);
NameDict* d = &pk_current_vm->cached_names; BinTree* d = &pk_current_vm->cached_names;
py_Ref res = NameDict__try_get(d, name); py_Ref res = BinTree__try_get(d, name);
if(res != NULL) return res; if(res != NULL) return res;
// not found, create a new one // not found, create a new one
py_TValue tmp; py_StackRef tmp = py_pushtmp();
py_newstrv(&tmp, py_name2sv(name)); py_newstrv(tmp, py_name2sv(name));
NameDict__set(d, name, &tmp); BinTree__set(d, name, tmp);
return NameDict__try_get(d, name); py_pop();
return BinTree__try_get(d, name);
} }

72
src/objects/bintree.c Normal file
View File

@ -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);
}

View File

@ -1,93 +1,10 @@
#include "pocketpy/objects/namedict.h" #include "pocketpy/objects/namedict.h"
#include "pocketpy/common/utils.h" #include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/pocketpy.h"
#include <stdint.h> #include <stdint.h>
#include <string.h>
void ModuleDict__ctor(ModuleDict* self, const char* path, py_TValue module) { #include <assert.h>
assert(path != NULL); #include <stdlib.h>
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 ///////////////////
#define HASH_PROBE_1(__k, ok, i) \ #define HASH_PROBE_1(__k, ok, i) \
ok = false; \ ok = false; \

View File

@ -13,7 +13,7 @@
py_Ref py_getmodule(const char* path) { py_Ref py_getmodule(const char* path) {
VM* vm = pk_current_vm; 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); } 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 // we do not allow override in order to avoid memory leak
// it is because Module objects are not garbage collected // 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); if(exists) c11__abort("module '%s' already exists", path);
// convert to a weak (const char*) // convert to a weak (const char*)
path = py_tostr(py_getdict(r0, __path__)); 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); py_shrink(2);
return py_getmodule(path); return py_getmodule(path);

View File

@ -34,3 +34,26 @@ assert d.i == 1
assert d.j == 2 assert d.j == 2
assert d.k == 'default' assert d.k == 'default'
assert d.sum() == 3 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'