mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
backup
This commit is contained in:
parent
2f2a7b53fd
commit
1bd7ad0189
@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct NameDict {
|
||||
|
||||
} NameDict;
|
@ -23,6 +23,9 @@
|
||||
abort(); \
|
||||
} while(0)
|
||||
|
||||
#define c11__rtassert(cond) \
|
||||
if(!(cond)) c11__abort("Runtime assertion failed: %s", #cond)
|
||||
|
||||
#define c11__min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define c11__max(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
@ -42,4 +45,3 @@ typedef struct RefCounted {
|
||||
PK_FREE(obj); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
@ -60,6 +60,12 @@
|
||||
#define PK_M_DEG2RAD 0.017453292519943295
|
||||
#define PK_M_RAD2DEG 57.29577951308232
|
||||
|
||||
// Hash table load factor (smaller ones mean less collision but more memory)
|
||||
// For class instance
|
||||
#define PK_INST_ATTR_LOAD_FACTOR 0.67
|
||||
// For class itself
|
||||
#define PK_TYPE_ATTR_LOAD_FACTOR 0.5
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PK_PLATFORM_SEP '\\'
|
||||
#else
|
||||
|
@ -1,9 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "pocketpy/common/memorypool.h"
|
||||
#include "pocketpy/objects/codeobject.h"
|
||||
#include "pocketpy/objects/namedict.h"
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
void FastLocals__to_dict(py_TValue* locals, const CodeObject* co) PY_RETURN;
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include "pocketpy/pocketpy.h"
|
||||
#include "pocketpy/objects/object.h"
|
||||
|
||||
#define PK_MAGIC_SLOTS_COMMON_LENGTH (__missing__ - __xor__)
|
||||
#define PK_MAGIC_SLOTS_UNCOMMON_LENGTH (__xor__ + 1)
|
||||
#define PK_MAX_CHUNK_LENGTH 256
|
||||
|
||||
typedef struct py_TypeInfo {
|
||||
@ -25,8 +23,7 @@ typedef struct py_TypeInfo {
|
||||
void (*on_end_subclass)(struct py_TypeInfo*); // backdoor for enum module
|
||||
|
||||
/* Magic Slots */
|
||||
py_TValue magic_0[PK_MAGIC_SLOTS_COMMON_LENGTH]; // common magic slots
|
||||
py_TValue* magic_1; // uncommon magic slots
|
||||
// (deleted)
|
||||
} py_TypeInfo;
|
||||
|
||||
typedef struct TypeList {
|
||||
|
@ -1,16 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "pocketpy/common/vector.h"
|
||||
#include "pocketpy/common/str.h"
|
||||
#include "pocketpy/objects/base.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define SMALLMAP_T__HEADER
|
||||
#define K uint16_t
|
||||
#define V py_TValue
|
||||
#define NAME NameDict
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__HEADER
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
/* A simple binary tree for storing modules. */
|
||||
typedef struct ModuleDict {
|
||||
@ -26,3 +18,29 @@ 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;
|
||||
} NameDict_KV;
|
||||
|
||||
// https://github.com/pocketpy/pocketpy/blob/v1.x/include/pocketpy/namedict.h
|
||||
typedef struct NameDict {
|
||||
int length;
|
||||
float load_factor;
|
||||
int capacity;
|
||||
int critical_size;
|
||||
uintptr_t mask;
|
||||
NameDict_KV* items;
|
||||
} NameDict;
|
||||
|
||||
NameDict* NameDict__new(float load_factor);
|
||||
void NameDict__ctor(NameDict* self, float load_factor);
|
||||
void NameDict__dtor(NameDict* self);
|
||||
py_TValue* NameDict__try_get(NameDict* self, py_Name key);
|
||||
bool NameDict__contains(NameDict* self, py_Name key);
|
||||
void NameDict__set(NameDict* self, py_Name key, py_TValue* value);
|
||||
bool NameDict__del(NameDict* self, py_Name key);
|
||||
void NameDict__clear(NameDict* self);
|
@ -70,7 +70,7 @@ static bool unpack_dict_to_buffer(py_Ref key, py_Ref val, void* ctx) {
|
||||
py_TValue** p = ctx;
|
||||
if(py_isstr(key)) {
|
||||
py_Name name = py_namev(py_tosv(key));
|
||||
py_newint(*p, name);
|
||||
py_newint(*p, (uintptr_t)name);
|
||||
py_assign(*p + 1, val);
|
||||
(*p) += 2;
|
||||
return true;
|
||||
@ -80,7 +80,8 @@ static bool unpack_dict_to_buffer(py_Ref key, py_Ref val, void* ctx) {
|
||||
|
||||
FrameResult VM__run_top_frame(VM* self) {
|
||||
py_Frame* frame = self->top_frame;
|
||||
Bytecode* codes;
|
||||
Bytecode* co_codes;
|
||||
py_Name* co_names;
|
||||
|
||||
const py_Frame* base_frame = frame;
|
||||
|
||||
@ -91,11 +92,12 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
py_exception(tp_RecursionError, "maximum recursion depth exceeded");
|
||||
goto __ERROR;
|
||||
}
|
||||
codes = frame->co->codes.data;
|
||||
co_codes = frame->co->codes.data;
|
||||
co_names = frame->co->names.data;
|
||||
frame->ip++;
|
||||
|
||||
__NEXT_STEP:
|
||||
byte = codes[frame->ip];
|
||||
byte = co_codes[frame->ip];
|
||||
|
||||
if(self->trace_info.func) {
|
||||
SourceLocation loc = Frame__source_location(frame);
|
||||
@ -195,7 +197,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
ud->closure = FastLocals__to_namedict(frame->locals, frame->co);
|
||||
py_Name name = py_name(decl->code.name->data);
|
||||
// capture itself to allow recursion
|
||||
NameDict__set(ud->closure, name, *SP());
|
||||
NameDict__set(ud->closure, name, SP());
|
||||
}
|
||||
SP()++;
|
||||
DISPATCH();
|
||||
@ -217,7 +219,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
case OP_LOAD_NAME: {
|
||||
assert(frame->is_locals_special);
|
||||
py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
|
||||
py_Name name = co_names[byte.arg];
|
||||
// locals
|
||||
switch(frame->locals->type) {
|
||||
case tp_locals: {
|
||||
@ -261,7 +263,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
goto __ERROR;
|
||||
}
|
||||
case OP_LOAD_NONLOCAL: {
|
||||
py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
|
||||
py_Name name = co_names[byte.arg];
|
||||
py_Ref tmp = Frame__getclosure(frame, name);
|
||||
if(tmp != NULL) {
|
||||
PUSH(tmp);
|
||||
@ -283,7 +285,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
goto __ERROR;
|
||||
}
|
||||
case OP_LOAD_GLOBAL: {
|
||||
py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
|
||||
py_Name name = co_names[byte.arg];
|
||||
int res = Frame__getglobal(frame, name);
|
||||
if(res == 1) {
|
||||
PUSH(&self->last_retval);
|
||||
@ -299,7 +301,8 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
goto __ERROR;
|
||||
}
|
||||
case OP_LOAD_ATTR: {
|
||||
if(py_getattr(TOP(), byte.arg)) {
|
||||
py_Name name = co_names[byte.arg];
|
||||
if(py_getattr(TOP(), name)) {
|
||||
py_assign(TOP(), py_retval());
|
||||
} else {
|
||||
goto __ERROR;
|
||||
@ -308,7 +311,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
case OP_LOAD_CLASS_GLOBAL: {
|
||||
assert(self->curr_class);
|
||||
py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
|
||||
py_Name name = co_names[byte.arg];
|
||||
py_Ref tmp = py_getdict(self->curr_class, name);
|
||||
if(tmp) {
|
||||
PUSH(tmp);
|
||||
@ -331,10 +334,11 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
case OP_LOAD_METHOD: {
|
||||
// [self] -> [unbound, self]
|
||||
bool ok = py_pushmethod(byte.arg);
|
||||
py_Name name = co_names[byte.arg];
|
||||
bool ok = py_pushmethod(name);
|
||||
if(!ok) {
|
||||
// fallback to getattr
|
||||
if(py_getattr(TOP(), byte.arg)) {
|
||||
if(py_getattr(TOP(), name)) {
|
||||
py_assign(TOP(), py_retval());
|
||||
py_newnil(SP()++);
|
||||
} else {
|
||||
@ -368,7 +372,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
case OP_STORE_NAME: {
|
||||
assert(frame->is_locals_special);
|
||||
py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
|
||||
py_Name name = co_names[byte.arg];
|
||||
switch(frame->locals->type) {
|
||||
case tp_locals: {
|
||||
py_Frame* noproxy = frame->locals->_ptr;
|
||||
@ -395,13 +399,15 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
}
|
||||
case OP_STORE_GLOBAL: {
|
||||
if(!Frame__setglobal(frame, byte.arg, TOP())) goto __ERROR;
|
||||
py_Name name = co_names[byte.arg];
|
||||
if(!Frame__setglobal(frame, name, TOP())) goto __ERROR;
|
||||
POP();
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_STORE_ATTR: {
|
||||
// [val, a] -> a.b = val
|
||||
if(!py_setattr(TOP(), byte.arg, SECOND())) goto __ERROR;
|
||||
py_Name name = co_names[byte.arg];
|
||||
if(!py_setattr(TOP(), name, SECOND())) goto __ERROR;
|
||||
STACK_SHRINK(2);
|
||||
DISPATCH();
|
||||
}
|
||||
@ -435,7 +441,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
case OP_DELETE_NAME: {
|
||||
assert(frame->is_locals_special);
|
||||
py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
|
||||
py_Name name = co_names[byte.arg];
|
||||
switch(frame->locals->type) {
|
||||
case tp_locals: {
|
||||
py_Frame* noproxy = frame->locals->_ptr;
|
||||
@ -464,7 +470,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
}
|
||||
case OP_DELETE_GLOBAL: {
|
||||
py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
|
||||
py_Name name = co_names[byte.arg];
|
||||
int res = Frame__delglobal(frame, name);
|
||||
if(res == 1) DISPATCH();
|
||||
if(res == -1) goto __ERROR;
|
||||
@ -473,7 +479,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
|
||||
case OP_DELETE_ATTR: {
|
||||
py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
|
||||
py_Name name = co_names[byte.arg];
|
||||
if(!py_delattr(TOP(), name)) goto __ERROR;
|
||||
DISPATCH();
|
||||
}
|
||||
@ -896,8 +902,8 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
} else {
|
||||
for(int i = 0; i < dict->length; i++) {
|
||||
NameDict_KV* kv = c11__at(NameDict_KV, dict, i);
|
||||
if(!kv->key) continue;
|
||||
NameDict_KV* kv = &dict->items[i];
|
||||
if(kv->key == NULL) continue;
|
||||
c11_sv name = py_name2sv(kv->key);
|
||||
if(name.size == 0 || name.data[0] == '_') continue;
|
||||
if(!Frame__setglobal(frame, kv->key, &kv->value)) goto __ERROR;
|
||||
@ -1000,7 +1006,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
///////////
|
||||
case OP_BEGIN_CLASS: {
|
||||
// [base]
|
||||
py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
|
||||
py_Name name = co_names[byte.arg];
|
||||
py_Type base;
|
||||
if(py_isnone(TOP())) {
|
||||
base = tp_object;
|
||||
@ -1028,7 +1034,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
case OP_END_CLASS: {
|
||||
// [cls or decorated]
|
||||
py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
|
||||
py_Name name = co_names[byte.arg];
|
||||
if(!Frame__setglobal(frame, name, TOP())) goto __ERROR;
|
||||
|
||||
if(py_istype(TOP(), tp_type)) {
|
||||
@ -1038,9 +1044,9 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
py_TypeInfo* base_ti = ti->base_ti;
|
||||
if(base_ti->on_end_subclass) base_ti->on_end_subclass(ti);
|
||||
}
|
||||
py_TValue* slot_eq = TypeList__magic_common(ti, __eq__);
|
||||
py_TValue* slot_ne = TypeList__magic_common(ti, __ne__);
|
||||
if(!py_isnil(slot_eq) && py_isnil(slot_ne)) {
|
||||
py_TValue* slot_eq = py_getdict(&ti->self, __eq__);
|
||||
py_TValue* slot_ne = py_getdict(&ti->self, __ne__);
|
||||
if(slot_eq && !slot_ne) {
|
||||
TypeError("'%n' implements '__eq__' but not '__ne__'", ti->name);
|
||||
goto __ERROR;
|
||||
}
|
||||
@ -1053,7 +1059,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
case OP_STORE_CLASS_ATTR: {
|
||||
assert(self->curr_class);
|
||||
py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
|
||||
py_Name name = co_names[byte.arg];
|
||||
// TOP() can be a function, classmethod or custom decorator
|
||||
py_Ref actual_func = TOP();
|
||||
if(actual_func->type == tp_classmethod) {
|
||||
@ -1073,7 +1079,8 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
py_Type type = py_totype(self->curr_class);
|
||||
py_TypeInfo* ti = TypeList__get(&self->types, type);
|
||||
if(py_isnil(&ti->annotations)) py_newdict(&ti->annotations);
|
||||
bool ok = py_dict_setitem_by_str(&ti->annotations, py_name2str(byte.arg), TOP());
|
||||
py_Name name = co_names[byte.arg];
|
||||
bool ok = py_dict_setitem_by_str(&ti->annotations, py_name2str(name), TOP());
|
||||
if(!ok) goto __ERROR;
|
||||
POP();
|
||||
DISPATCH();
|
||||
@ -1212,7 +1219,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
frame = self->top_frame;
|
||||
codes = frame->co->codes.data;
|
||||
co_codes = frame->co->codes.data;
|
||||
goto __ERROR;
|
||||
}
|
||||
}
|
||||
@ -1221,30 +1228,28 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
|
||||
const char* pk_op2str(py_Name op) {
|
||||
switch(op) {
|
||||
case __eq__: return "==";
|
||||
case __ne__: return "!=";
|
||||
case __lt__: return "<";
|
||||
case __le__: return "<=";
|
||||
case __gt__: return ">";
|
||||
case __ge__: return ">=";
|
||||
case __add__: return "+";
|
||||
case __sub__: return "-";
|
||||
case __mul__: return "*";
|
||||
case __truediv__: return "/";
|
||||
case __floordiv__: return "//";
|
||||
case __mod__: return "%";
|
||||
case __pow__: return "**";
|
||||
case __lshift__: return "<<";
|
||||
case __rshift__: return ">>";
|
||||
case __and__: return "&";
|
||||
case __or__: return "|";
|
||||
case __xor__: return "^";
|
||||
case __neg__: return "-";
|
||||
case __invert__: return "~";
|
||||
case __matmul__: return "@";
|
||||
default: return py_name2str(op);
|
||||
}
|
||||
if(__eq__ == op) return "==";
|
||||
if(__ne__ == op) return "!=";
|
||||
if(__lt__ == op) return "<";
|
||||
if(__le__ == op) return "<=";
|
||||
if(__gt__ == op) return ">";
|
||||
if(__ge__ == op) return ">=";
|
||||
if(__add__ == op) return "+";
|
||||
if(__sub__ == op) return "-";
|
||||
if(__mul__ == op) return "*";
|
||||
if(__truediv__ == op) return "/";
|
||||
if(__floordiv__ == op) return "//";
|
||||
if(__mod__ == op) return "%";
|
||||
if(__pow__ == op) return "**";
|
||||
if(__lshift__ == op) return "<<";
|
||||
if(__rshift__ == op) return ">>";
|
||||
if(__and__ == op) return "&";
|
||||
if(__or__ == op) return "|";
|
||||
if(__xor__ == op) return "^";
|
||||
if(__neg__ == op) return "-";
|
||||
if(__invert__ == op) return "~";
|
||||
if(__matmul__ == op) return "@";
|
||||
return py_name2str(op);
|
||||
}
|
||||
|
||||
bool pk_stack_binaryop(VM* self, py_Name op, py_Name rop) {
|
||||
|
@ -29,10 +29,10 @@ void FastLocals__to_dict(py_TValue* locals, const CodeObject* co) {
|
||||
}
|
||||
|
||||
NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co) {
|
||||
NameDict* dict = NameDict__new();
|
||||
NameDict* dict = NameDict__new(PK_INST_ATTR_LOAD_FACTOR);
|
||||
c11__foreach(c11_smallmap_n2i_KV, &co->varnames_inv, entry) {
|
||||
py_TValue value = locals[entry->value];
|
||||
if(!py_isnil(&value)) NameDict__set(dict, entry->key, value);
|
||||
py_Ref val = &locals[entry->value];
|
||||
if(!py_isnil(val)) NameDict__set(dict, entry->key, val);
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
@ -653,20 +653,6 @@ void ManagedHeap__mark(ManagedHeap* self) {
|
||||
py_TypeInfo* ti = TypeList__get(&vm->types, i);
|
||||
// mark type object
|
||||
pk__mark_value(&ti->self);
|
||||
// mark common magic slots
|
||||
for(int j = 0; j < PK_MAGIC_SLOTS_COMMON_LENGTH; j++) {
|
||||
py_TValue* slot = ti->magic_0 + j;
|
||||
if(py_isnil(slot)) continue;
|
||||
pk__mark_value(slot);
|
||||
}
|
||||
// mark uncommon magic slots
|
||||
if(ti->magic_1) {
|
||||
for(int j = 0; j < PK_MAGIC_SLOTS_UNCOMMON_LENGTH; j++) {
|
||||
py_TValue* slot = ti->magic_1 + j;
|
||||
if(py_isnil(slot)) continue;
|
||||
pk__mark_value(slot);
|
||||
}
|
||||
}
|
||||
// mark type annotations
|
||||
pk__mark_value(&ti->annotations);
|
||||
}
|
||||
@ -701,7 +687,8 @@ void ManagedHeap__mark(ManagedHeap* self) {
|
||||
} else if(obj->slots == -1) {
|
||||
NameDict* namedict = PyObject__dict(obj);
|
||||
for(int i = 0; i < namedict->length; i++) {
|
||||
NameDict_KV* kv = c11__at(NameDict_KV, namedict, i);
|
||||
NameDict_KV* kv = &namedict->items[i];
|
||||
if(kv->key == NULL) continue;
|
||||
pk__mark_value(&kv->value);
|
||||
}
|
||||
}
|
||||
|
@ -375,7 +375,8 @@ static bool pkl__write_object(PickleObject* buf, py_TValue* obj) {
|
||||
if(ti->is_python) {
|
||||
NameDict* dict = PyObject__dict(obj->_obj);
|
||||
for(int i = dict->length - 1; i >= 0; i--) {
|
||||
NameDict_KV* kv = c11__at(NameDict_KV, dict, i);
|
||||
NameDict_KV* kv = &dict->items[i];
|
||||
if(kv->key == NULL) continue;
|
||||
if(!pkl__write_object(buf, &kv->value)) return false;
|
||||
}
|
||||
pkl__emit_op(buf, PKL_OBJECT);
|
||||
@ -383,7 +384,8 @@ static bool pkl__write_object(PickleObject* buf, py_TValue* obj) {
|
||||
buf->used_types[obj->type] = true;
|
||||
pkl__emit_int(buf, dict->length);
|
||||
for(int i = 0; i < dict->length; i++) {
|
||||
NameDict_KV* kv = c11__at(NameDict_KV, dict, i);
|
||||
NameDict_KV* kv = &dict->items[i];
|
||||
if(kv->key == NULL) continue;
|
||||
c11_sv field = py_name2sv(kv->key);
|
||||
// include '\0'
|
||||
PickleObject__write_bytes(buf, field.data, field.size + 1);
|
||||
@ -685,7 +687,7 @@ bool py_pickle_loads_body(const unsigned char* p, int memo_length, c11_smallmap_
|
||||
for(int i = 0; i < dict_length; i++) {
|
||||
py_StackRef value = py_peek(-1);
|
||||
c11_sv field = {(const char*)p, strlen((const char*)p)};
|
||||
NameDict__set(dict, py_namev(field), *value);
|
||||
NameDict__set(dict, py_namev(field), value);
|
||||
py_pop();
|
||||
p += field.size + 1;
|
||||
}
|
||||
|
@ -1,12 +1,8 @@
|
||||
#include "pocketpy/objects/namedict.h"
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/objects/object.h"
|
||||
|
||||
#define SMALLMAP_T__SOURCE
|
||||
#define K uint16_t
|
||||
#define V py_TValue
|
||||
#define NAME NameDict
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__SOURCE
|
||||
#include "pocketpy/pocketpy.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void ModuleDict__ctor(ModuleDict* self, const char* path, py_TValue module) {
|
||||
assert(path != NULL);
|
||||
@ -90,3 +86,122 @@ void ModuleDict__apply_mark(ModuleDict* self, c11_vector* p_stack) {
|
||||
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) \
|
||||
ok = false; \
|
||||
i = (uintptr_t)(__k) & self->mask; \
|
||||
while(self->items[i].key != NULL) { \
|
||||
if(self->items[i].key == (__k)) { \
|
||||
ok = true; \
|
||||
break; \
|
||||
} \
|
||||
i = (i + 1) & self->mask; \
|
||||
}
|
||||
|
||||
#define HASH_PROBE_0 HASH_PROBE_1
|
||||
|
||||
static void NameDict__set_capacity_and_alloc_items(NameDict* self, int val) {
|
||||
self->capacity = val;
|
||||
self->critical_size = val * self->load_factor;
|
||||
self->mask = (uintptr_t)val - 1;
|
||||
|
||||
self->items = PK_MALLOC(self->capacity * sizeof(NameDict_KV));
|
||||
memset(self->items, 0, self->capacity * sizeof(NameDict_KV));
|
||||
}
|
||||
|
||||
static void NameDict__rehash_2x(NameDict* self) {
|
||||
NameDict_KV* old_items = self->items;
|
||||
int old_capacity = self->capacity;
|
||||
NameDict__set_capacity_and_alloc_items(self, self->capacity * 2);
|
||||
for(int i = 0; i < old_capacity; i++) {
|
||||
if(old_items[i].key == NULL) continue;
|
||||
bool ok;
|
||||
uintptr_t j;
|
||||
HASH_PROBE_1(old_items[i].key, ok, j);
|
||||
c11__rtassert(!ok);
|
||||
self->items[j] = old_items[i];
|
||||
}
|
||||
PK_FREE(old_items);
|
||||
}
|
||||
|
||||
NameDict* NameDict__new(float load_factor) {
|
||||
NameDict* p = PK_MALLOC(sizeof(NameDict));
|
||||
NameDict__ctor(p, load_factor);
|
||||
return p;
|
||||
}
|
||||
|
||||
void NameDict__ctor(NameDict* self, float load_factor) {
|
||||
assert(load_factor > 0.0f && load_factor < 1.0f);
|
||||
self->length = 0;
|
||||
self->load_factor = load_factor;
|
||||
NameDict__set_capacity_and_alloc_items(self, 4);
|
||||
}
|
||||
|
||||
void NameDict__dtor(NameDict* self) { PK_FREE(self->items); }
|
||||
|
||||
py_TValue* NameDict__try_get(NameDict* self, py_Name key) {
|
||||
bool ok;
|
||||
uintptr_t i;
|
||||
HASH_PROBE_0(key, ok, i);
|
||||
if(!ok) return NULL;
|
||||
return &self->items[i].value;
|
||||
}
|
||||
|
||||
bool NameDict__contains(NameDict* self, py_Name key) {
|
||||
bool ok;
|
||||
uintptr_t i;
|
||||
HASH_PROBE_0(key, ok, i);
|
||||
return ok;
|
||||
}
|
||||
|
||||
void NameDict__set(NameDict* self, py_Name key, py_TValue* val) {
|
||||
bool ok;
|
||||
uintptr_t i;
|
||||
HASH_PROBE_1(key, ok, i);
|
||||
if(!ok) {
|
||||
self->length++;
|
||||
if(self->length > self->critical_size) {
|
||||
NameDict__rehash_2x(self);
|
||||
HASH_PROBE_1(key, ok, i);
|
||||
}
|
||||
self->items[i].key = key;
|
||||
}
|
||||
self->items[i].value = *val;
|
||||
}
|
||||
|
||||
bool NameDict__del(NameDict* self, py_Name key) {
|
||||
bool ok;
|
||||
uintptr_t i;
|
||||
HASH_PROBE_0(key, ok, i);
|
||||
if(!ok) return false;
|
||||
self->items[i].key = NULL;
|
||||
self->items[i].value = *py_NIL();
|
||||
self->length--;
|
||||
// tidy
|
||||
uintptr_t pre_z = i;
|
||||
uintptr_t z = (i + 1) & self->mask;
|
||||
while(self->items[z].key != NULL) {
|
||||
uintptr_t h = (uintptr_t)self->items[z].key & self->mask;
|
||||
if(h != i) break;
|
||||
// std::swap(_items[pre_z], _items[z]);
|
||||
NameDict_KV tmp = self->items[pre_z];
|
||||
self->items[pre_z] = self->items[z];
|
||||
self->items[z] = tmp;
|
||||
pre_z = z;
|
||||
z = (z + 1) & self->mask;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void NameDict__clear(NameDict* self) {
|
||||
for(int i = 0; i < self->capacity; i++) {
|
||||
self->items[i].key = NULL;
|
||||
self->items[i].value = *py_NIL();
|
||||
}
|
||||
self->length = 0;
|
||||
}
|
||||
|
||||
#undef HASH_PROBE_0
|
||||
#undef HASH_PROBE_1
|
@ -617,7 +617,7 @@ static bool
|
||||
int max_index = -1;
|
||||
c11__foreach(Bytecode, &co->codes, bc) {
|
||||
if(bc->op == OP_LOAD_NAME) {
|
||||
c11_sv name = py_name2sv(bc->arg);
|
||||
c11_sv name = py_name2sv(c11__getitem(py_Name, &co->names, bc->arg));
|
||||
if(name.data[0] != '_') continue;
|
||||
int index;
|
||||
if(name.size == 1) {
|
||||
@ -766,7 +766,8 @@ void function__gc_mark(void* ud, c11_vector* p_stack) {
|
||||
if(func->closure) {
|
||||
NameDict* namedict = func->closure;
|
||||
for(int i = 0; i < namedict->length; i++) {
|
||||
NameDict_KV* kv = c11__at(NameDict_KV, namedict, i);
|
||||
NameDict_KV* kv = &namedict->items[i];
|
||||
if(kv->key == NULL) continue;
|
||||
pk__mark_value(&kv->value);
|
||||
}
|
||||
}
|
||||
|
@ -52,29 +52,11 @@ static bool namedict_items(int argc, py_Ref argv) {
|
||||
py_Ref object = py_getslot(argv, 0);
|
||||
NameDict* dict = PyObject__dict(object->_obj);
|
||||
py_newlist(py_retval());
|
||||
if(object->type == tp_type) {
|
||||
py_TypeInfo* ti = pk__type_info(py_totype(object));
|
||||
for(int j = 0; j < PK_MAGIC_SLOTS_COMMON_LENGTH; j++) {
|
||||
if(py_isnil(ti->magic_0 + j)) continue;
|
||||
py_Ref slot = py_list_emplace(py_retval());
|
||||
py_Ref p = py_newtuple(slot, 2);
|
||||
p[0] = *py_name2ref(j + PK_MAGIC_SLOTS_UNCOMMON_LENGTH);
|
||||
p[1] = ti->magic_0[j];
|
||||
}
|
||||
if(ti->magic_1) {
|
||||
for(int j = 0; j < PK_MAGIC_SLOTS_UNCOMMON_LENGTH; j++) {
|
||||
if(py_isnil(ti->magic_1 + j)) continue;
|
||||
py_Ref slot = py_list_emplace(py_retval());
|
||||
py_Ref p = py_newtuple(slot, 2);
|
||||
p[0] = *py_name2ref(j);
|
||||
p[1] = ti->magic_1[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < dict->length; i++) {
|
||||
py_Ref slot = py_list_emplace(py_retval());
|
||||
py_Ref p = py_newtuple(slot, 2);
|
||||
NameDict_KV* kv = c11__at(NameDict_KV, dict, i);
|
||||
NameDict_KV* kv = &dict->items[i];
|
||||
if(kv->key == NULL) continue;
|
||||
p[0] = *py_name2ref(kv->key);
|
||||
p[1] = kv->value;
|
||||
}
|
||||
|
@ -10,23 +10,12 @@ void py_setreg(int i, py_Ref val) { pk_current_vm->reg[i] = *val; }
|
||||
|
||||
py_Ref py_getdict(py_Ref self, py_Name name) {
|
||||
assert(self && self->is_ptr);
|
||||
if(!py_ismagicname(name) || self->type != tp_type) {
|
||||
return NameDict__try_get(PyObject__dict(self->_obj), name);
|
||||
} else {
|
||||
py_Type* ud = py_touserdata(self);
|
||||
py_Ref slot = py_tpgetmagic(*ud, name);
|
||||
return py_isnil(slot) ? NULL : slot;
|
||||
}
|
||||
return NameDict__try_get(PyObject__dict(self->_obj), name);
|
||||
}
|
||||
|
||||
void py_setdict(py_Ref self, py_Name name, py_Ref val) {
|
||||
assert(self && self->is_ptr);
|
||||
if(!py_ismagicname(name) || self->type != tp_type) {
|
||||
NameDict__set(PyObject__dict(self->_obj), name, *val);
|
||||
} else {
|
||||
py_Type* ud = py_touserdata(self);
|
||||
*py_tpgetmagic(*ud, name) = *val;
|
||||
}
|
||||
NameDict__set(PyObject__dict(self->_obj), name, val);
|
||||
}
|
||||
|
||||
py_ItemRef py_emplacedict(py_Ref self, py_Name name) {
|
||||
@ -38,7 +27,8 @@ bool py_applydict(py_Ref self, bool (*f)(py_Name, py_Ref, void*), void* ctx) {
|
||||
assert(self && self->is_ptr);
|
||||
NameDict* dict = PyObject__dict(self->_obj);
|
||||
for(int i = 0; i < dict->length; i++) {
|
||||
NameDict_KV* kv = c11__at(NameDict_KV, dict, i);
|
||||
NameDict_KV* kv = &dict->items[i];
|
||||
if(kv->key == NULL) continue;
|
||||
bool ok = f(kv->key, &kv->value, ctx);
|
||||
if(!ok) return false;
|
||||
}
|
||||
@ -47,13 +37,7 @@ bool py_applydict(py_Ref self, bool (*f)(py_Name, py_Ref, void*), void* ctx) {
|
||||
|
||||
bool py_deldict(py_Ref self, py_Name name) {
|
||||
assert(self && self->is_ptr);
|
||||
if(!py_ismagicname(name) || self->type != tp_type) {
|
||||
return NameDict__del(PyObject__dict(self->_obj), name);
|
||||
} else {
|
||||
py_Type* ud = py_touserdata(self);
|
||||
py_newnil(py_tpgetmagic(*ud, name));
|
||||
return true;
|
||||
}
|
||||
return NameDict__del(PyObject__dict(self->_obj), name);
|
||||
}
|
||||
|
||||
py_Ref py_getslot(py_Ref self, int i) {
|
||||
@ -119,7 +103,7 @@ void py_pushnone() {
|
||||
|
||||
void py_pushname(py_Name name) {
|
||||
VM* vm = pk_current_vm;
|
||||
py_newint(vm->stack.sp++, name);
|
||||
py_newint(vm->stack.sp++, (uintptr_t)name);
|
||||
}
|
||||
|
||||
py_Ref py_pushtmp() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user