This commit is contained in:
blueloveTH 2024-08-19 13:04:38 +08:00
parent f70d5af07f
commit aaf7a84a3a
13 changed files with 144 additions and 81 deletions

View File

@ -0,0 +1,36 @@
#pragma once
#include "pocketpy/pocketpy.h"
#include "pocketpy/objects/object.h"
typedef struct py_TypeInfo {
py_Name name;
py_Type base;
py_TValue self;
py_TValue module; // the module where the type is defined
bool is_python; // is it a python class? (not derived from c object)
bool is_sealed; // can it be subclassed?
void (*dtor)(void*);
py_TValue annotations; // type annotations
void (*on_end_subclass)(struct py_TypeInfo*); // backdoor for enum module
void (*gc_mark)(void* ud);
/* Magic Slots */
py_TValue magic[64];
} py_TypeInfo;
typedef struct TypeList {
int length;
py_TypeInfo* chunks[256];
} TypeList;
void TypeList__ctor(TypeList* self);
void TypeList__dtor(TypeList* self);
py_TypeInfo* TypeList__get(TypeList* self, py_Type index);
py_TypeInfo* TypeList__emplace(TypeList* self);
void TypeList__apply(TypeList* self, void (*f)(py_TypeInfo*, void*), void* ctx);

View File

@ -5,6 +5,7 @@
#include "pocketpy/interpreter/heap.h" #include "pocketpy/interpreter/heap.h"
#include "pocketpy/interpreter/frame.h" #include "pocketpy/interpreter/frame.h"
#include "pocketpy/interpreter/modules.h" #include "pocketpy/interpreter/modules.h"
#include "pocketpy/interpreter/typeinfo.h"
// TODO: // TODO:
// 1. __eq__ and __ne__ fallbacks // 1. __eq__ and __ne__ fallbacks
@ -15,32 +16,11 @@
// 6. py_TypeInfo // 6. py_TypeInfo
// 7. Direct assignment of py_NIL, py_True, py_False, py_None. They are slow. // 7. Direct assignment of py_NIL, py_True, py_False, py_None. They are slow.
typedef struct py_TypeInfo {
py_Name name;
py_Type base;
py_TValue self;
py_TValue module; // the module where the type is defined
bool is_python; // is it a python class? (not derived from c object)
bool is_sealed; // can it be subclassed?
void (*dtor)(void*);
py_TValue annotations; // type annotations
void (*on_end_subclass)(struct py_TypeInfo*); // backdoor for enum module
void (*gc_mark)(void* ud);
/* Magic Slots */
py_TValue magic[64];
} py_TypeInfo;
typedef struct VM { typedef struct VM {
Frame* top_frame; Frame* top_frame;
ModuleDict modules; ModuleDict modules;
c11_vector /*T=py_TypeInfo*/ types; TypeList types;
py_TValue builtins; // builtins module py_TValue builtins; // builtins module
py_TValue main; // __main__ module py_TValue main; // __main__ module
@ -74,6 +54,7 @@ void pk__mark_value(py_TValue*);
void pk__mark_namedict(NameDict*); void pk__mark_namedict(NameDict*);
void pk__tp_set_marker(py_Type type, void (*gc_mark)(void*)); void pk__tp_set_marker(py_Type type, void (*gc_mark)(void*));
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);
bool pk_wrapper__self(int argc, py_Ref argv); bool pk_wrapper__self(int argc, py_Ref argv);
bool pk_wrapper__NotImplementedError(int argc, py_Ref argv); bool pk_wrapper__NotImplementedError(int argc, py_Ref argv);

View File

@ -24,4 +24,4 @@ void ModuleDict__ctor(ModuleDict* self, const char* path, py_TValue module);
void ModuleDict__dtor(ModuleDict* self); void ModuleDict__dtor(ModuleDict* self);
void ModuleDict__set(ModuleDict* self, const char* key, py_TValue val); void ModuleDict__set(ModuleDict* self, const char* key, py_TValue val);
py_TValue* ModuleDict__try_get(ModuleDict* self, const char* path); py_TValue* ModuleDict__try_get(ModuleDict* self, const char* path);
bool ModuleDict__contains(ModuleDict* self, const char* path); bool ModuleDict__contains(ModuleDict* self, const char* path);

View File

@ -250,18 +250,18 @@ PK_EXPORT bool py_isinstance(py_Ref obj, py_Type type);
/// Check if the derived type is a subclass of the base type. /// Check if the derived type is a subclass of the base type.
PK_EXPORT bool py_issubclass(py_Type derived, py_Type base); PK_EXPORT bool py_issubclass(py_Type derived, py_Type base);
/// Get the magic method from the given type only.
/// The returned reference is always valid. However, its value may be `nil`.
PK_EXPORT py_GlobalRef py_tpgetmagic(py_Type type, py_Name name);
/// Search the magic method from the given type to the base type. /// Search the magic method from the given type to the base type.
/// Return `NULL` if not found. /// Return `NULL` if not found.
PK_EXPORT py_ItemRef py_tpfindmagic(py_Type, py_Name name); PK_EXPORT py_GlobalRef py_tpfindmagic(py_Type, py_Name name);
/// Search the name from the given type to the base type. /// Search the name from the given type to the base type.
/// Return `NULL` if not found. /// Return `NULL` if not found.
PK_EXPORT py_ItemRef py_tpfindname(py_Type, py_Name name); PK_EXPORT py_ItemRef py_tpfindname(py_Type, py_Name name);
/// Get the magic method from the given type only.
/// The returned reference is always valid. However, its value may be `nil`.
PK_EXPORT py_ItemRef py_tpgetmagic(py_Type type, py_Name name);
/// Get the type object of the given type. /// Get the type object of the given type.
PK_EXPORT py_ItemRef py_tpobject(py_Type type); PK_EXPORT py_GlobalRef py_tpobject(py_Type type);
/// Get the type name. /// Get the type name.
PK_EXPORT const char* py_tpname(py_Type type); PK_EXPORT const char* py_tpname(py_Type type);
/// Call a type to create a new instance. /// Call a type to create a new instance.

View File

@ -871,7 +871,7 @@ FrameResult VM__run_top_frame(VM* self) {
} }
POP(); POP();
py_TypeInfo* base_ti = c11__at(py_TypeInfo, &self->types, base); py_TypeInfo* base_ti = TypeList__get(&self->types, base);
if(base_ti->is_sealed) { if(base_ti->is_sealed) {
TypeError("type '%t' is not an acceptable base type", base); TypeError("type '%t' is not an acceptable base type", base);
goto __ERROR; goto __ERROR;
@ -892,9 +892,9 @@ FrameResult VM__run_top_frame(VM* self) {
if(py_istype(TOP(), tp_type)) { if(py_istype(TOP(), tp_type)) {
// call on_end_subclass // call on_end_subclass
py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, py_totype(TOP())); py_TypeInfo* ti = TypeList__get(&self->types, py_totype(TOP()));
if(ti->base != tp_object) { if(ti->base != tp_object) {
py_TypeInfo* base_ti = c11__at(py_TypeInfo, &self->types, ti->base); py_TypeInfo* base_ti = TypeList__get(&self->types, ti->base);
if(base_ti->on_end_subclass) base_ti->on_end_subclass(ti); if(base_ti->on_end_subclass) base_ti->on_end_subclass(ti);
} }
} }
@ -915,7 +915,7 @@ FrameResult VM__run_top_frame(VM* self) {
case OP_ADD_CLASS_ANNOTATION: { case OP_ADD_CLASS_ANNOTATION: {
// [type_hint string] // [type_hint string]
py_Type type = py_totype(self->__curr_class); py_Type type = py_totype(self->__curr_class);
py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, type); py_TypeInfo* ti = TypeList__get(&self->types, type);
if(py_isnil(&ti->annotations)) py_newdict(&ti->annotations); if(py_isnil(&ti->annotations)) py_newdict(&ti->annotations);
bool ok = py_dict_setitem_by_str(&ti->annotations, py_name2str(byte.arg), TOP()); bool ok = py_dict_setitem_by_str(&ti->annotations, py_name2str(byte.arg), TOP());
if(!ok) goto __ERROR; if(!ok) goto __ERROR;

View File

@ -0,0 +1,44 @@
#include "pocketpy/interpreter/typeinfo.h"
#define CHUNK_SIZE 128
#define LOG2_CHUNK_SIZE 7
static py_TypeInfo firstChunk[CHUNK_SIZE];
void TypeList__ctor(TypeList* self) {
self->length = 0;
memset(self->chunks, 0, sizeof(self->chunks));
self->chunks[0] = firstChunk;
}
void TypeList__dtor(TypeList* self) {
for (int i = 1; i < self->length; i++) {
if(self->chunks[i]) free(self->chunks[i]);
}
}
py_TypeInfo* TypeList__get(TypeList* self, py_Type index) {
assert(index < self->length);
int chunk = index >> LOG2_CHUNK_SIZE;
int offset = index & (CHUNK_SIZE - 1);
return self->chunks[chunk] + offset;
}
py_TypeInfo* TypeList__emplace(TypeList* self){
int chunk = self->length >> LOG2_CHUNK_SIZE;
int offset = self->length & (CHUNK_SIZE - 1);
assert(chunk < 256);
if(self->chunks[chunk] == NULL){
self->chunks[chunk] = malloc(sizeof(py_TypeInfo) * CHUNK_SIZE);
memset(self->chunks[chunk], 0, sizeof(py_TypeInfo) * CHUNK_SIZE);
}
self->length++;
return self->chunks[chunk] + offset;
}
void TypeList__apply(TypeList* self, void (*f)(py_TypeInfo*, void*), void* ctx) {
for (int i = 0; i < self->length; i++) {
py_TypeInfo* info = TypeList__get(self, i);
f(info, ctx);
}
}

View File

@ -4,6 +4,7 @@
#include "pocketpy/common/utils.h" #include "pocketpy/common/utils.h"
#include "pocketpy/interpreter/generator.h" #include "pocketpy/interpreter/generator.h"
#include "pocketpy/interpreter/modules.h" #include "pocketpy/interpreter/modules.h"
#include "pocketpy/interpreter/typeinfo.h"
#include "pocketpy/objects/base.h" #include "pocketpy/objects/base.h"
#include "pocketpy/common/_generated.h" #include "pocketpy/common/_generated.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
@ -56,7 +57,7 @@ void VM__ctor(VM* self) {
self->top_frame = NULL; self->top_frame = NULL;
ModuleDict__ctor(&self->modules, NULL, *py_NIL); ModuleDict__ctor(&self->modules, NULL, *py_NIL);
c11_vector__ctor(&self->types, sizeof(py_TypeInfo)); TypeList__ctor(&self->types);
self->builtins = *py_NIL; self->builtins = *py_NIL;
self->main = *py_NIL; self->main = *py_NIL;
@ -76,7 +77,7 @@ void VM__ctor(VM* self) {
/* Init Builtin Types */ /* Init Builtin Types */
// 0: unused // 0: unused
void* placeholder = c11_vector__emplace(&self->types); void* placeholder = TypeList__emplace(&self->types);
memset(placeholder, 0, sizeof(py_TypeInfo)); memset(placeholder, 0, sizeof(py_TypeInfo));
#define validate(t, expr) \ #define validate(t, expr) \
@ -187,7 +188,7 @@ void VM__ctor(VM* self) {
}; };
for(int i = 0; i < c11__count_array(public_types); i++) { for(int i = 0; i < c11__count_array(public_types); i++) {
py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, public_types[i]); py_TypeInfo* ti = pk__type_info(public_types[i]);
py_setdict(&self->builtins, ti->name, &ti->self); py_setdict(&self->builtins, ti->name, &ti->self);
} }
@ -228,7 +229,7 @@ void VM__dtor(VM* self) {
while(self->top_frame) while(self->top_frame)
VM__pop_frame(self); VM__pop_frame(self);
ModuleDict__dtor(&self->modules); ModuleDict__dtor(&self->modules);
c11_vector__dtor(&self->types); TypeList__dtor(&self->types);
ValueStack__clear(&self->stack); ValueStack__clear(&self->stack);
} }
@ -316,10 +317,9 @@ py_Type pk_newtype(const char* name,
void (*dtor)(void*), void (*dtor)(void*),
bool is_python, bool is_python,
bool is_sealed) { bool is_sealed) {
c11_vector* types = &pk_current_vm->types; py_Type index = pk_current_vm->types.length;
py_Type index = types->length; py_TypeInfo* ti = TypeList__emplace(&pk_current_vm->types);
py_TypeInfo* ti = c11_vector__emplace(types); py_TypeInfo* base_ti = base ? pk__type_info(base) : NULL;
py_TypeInfo* base_ti = base ? c11__at(py_TypeInfo, types, base) : NULL;
if(base_ti && base_ti->is_sealed) { if(base_ti && base_ti->is_sealed) {
c11__abort("type '%s' is not an acceptable base type", py_name2str(base_ti->name)); c11__abort("type '%s' is not an acceptable base type", py_name2str(base_ti->name));
} }
@ -540,7 +540,7 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
/****************************************/ /****************************************/
void PyObject__delete(PyObject* self) { void PyObject__delete(PyObject* self) {
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, self->type); py_TypeInfo* ti = pk__type_info(self->type);
if(ti->dtor) ti->dtor(PyObject__userdata(self)); if(ti->dtor) ti->dtor(PyObject__userdata(self));
if(self->slots == -1) NameDict__dtor(PyObject__dict(self)); if(self->slots == -1) NameDict__dtor(PyObject__dict(self));
if(self->gc_is_large) { if(self->gc_is_large) {
@ -564,7 +564,7 @@ void pk__mark_namedict(NameDict* dict) {
} }
void pk__tp_set_marker(py_Type type, void (*gc_mark)(void*)) { void pk__tp_set_marker(py_Type type, void (*gc_mark)(void*)) {
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type); py_TypeInfo* ti = pk__type_info(type);
assert(ti->gc_mark == NULL); assert(ti->gc_mark == NULL);
ti->gc_mark = gc_mark; ti->gc_mark = gc_mark;
} }
@ -582,8 +582,8 @@ static void mark_object(PyObject* obj) {
pk__mark_namedict(dict); pk__mark_namedict(dict);
} }
py_TypeInfo* types = c11__at(py_TypeInfo, &pk_current_vm->types, obj->type); py_TypeInfo* ti = pk__type_info(obj->type);
if(types->gc_mark) types->gc_mark(PyObject__userdata(obj)); if(ti->gc_mark) ti->gc_mark(PyObject__userdata(obj));
} }
void CodeObject__gc_mark(const CodeObject* self) { void CodeObject__gc_mark(const CodeObject* self) {
@ -603,18 +603,18 @@ void ManagedHeap__mark(ManagedHeap* self) {
pk__mark_value(p); pk__mark_value(p);
} }
// mark types // mark types
py_TypeInfo* types = vm->types.data;
int types_length = vm->types.length; int types_length = vm->types.length;
// 0-th type is placeholder // 0-th type is placeholder
for(int i = 1; i < types_length; i++) { for(py_Type i = 1; i < types_length; i++) {
py_TypeInfo* ti = TypeList__get(&vm->types, i);
// mark magic slots // mark magic slots
for(int j = 0; j <= __missing__; j++) { for(int j = 0; j <= __missing__; j++) {
py_TValue* slot = types[i].magic + j; py_TValue* slot = ti->magic + j;
if(py_isnil(slot)) continue; if(py_isnil(slot)) continue;
pk__mark_value(slot); pk__mark_value(slot);
} }
// mark type annotations // mark type annotations
pk__mark_value(&types[i].annotations); pk__mark_value(&ti->annotations);
} }
// mark frame // mark frame
for(Frame* frame = vm->top_frame; frame; frame = frame->f_back) { for(Frame* frame = vm->top_frame; frame; frame = frame->f_back) {
@ -695,4 +695,8 @@ bool pk_wrapper__self(int argc, py_Ref argv) {
bool pk_wrapper__NotImplementedError(int argc, py_Ref argv) { bool pk_wrapper__NotImplementedError(int argc, py_Ref argv) {
return py_exception(tp_NotImplementedError, ""); return py_exception(tp_NotImplementedError, "");
} }
py_TypeInfo* pk__type_info(py_Type type) {
return TypeList__get(&pk_current_vm->types, type);
}

View File

@ -86,6 +86,6 @@ void pk__add_module_enum() {
py_bindproperty(type, "name", Enum__name, NULL); py_bindproperty(type, "name", Enum__name, NULL);
py_bindproperty(type, "value", Enum__value, NULL); py_bindproperty(type, "value", Enum__value, NULL);
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type); py_TypeInfo* ti = pk__type_info(type);
ti->on_end_subclass = Enum__on_end_subclass; ti->on_end_subclass = Enum__on_end_subclass;
} }

View File

@ -1,4 +1,5 @@
#include "pocketpy/common/str.h" #include "pocketpy/common/str.h"
#include "pocketpy/objects/base.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h" #include "pocketpy/common/utils.h"
@ -49,10 +50,10 @@ bool py_checktype(py_Ref self, py_Type type) {
bool py_isinstance(py_Ref obj, py_Type type) { return py_issubclass(obj->type, type); } bool py_isinstance(py_Ref obj, py_Type type) { return py_issubclass(obj->type, type); }
bool py_issubclass(py_Type derived, py_Type base) { bool py_issubclass(py_Type derived, py_Type base) {
py_TypeInfo* types = pk_current_vm->types.data; TypeList* types = &pk_current_vm->types;
do { do {
if(derived == base) return true; if(derived == base) return true;
derived = types[derived].base; derived = TypeList__get(types, derived)->base;
} while(derived); } while(derived);
return false; return false;
} }

View File

@ -1,3 +1,4 @@
#include "pocketpy/interpreter/typeinfo.h"
#include "pocketpy/objects/codeobject.h" #include "pocketpy/objects/codeobject.h"
#include "pocketpy/objects/sourcedata.h" #include "pocketpy/objects/sourcedata.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
@ -178,7 +179,7 @@ bool pk_loadmethod(py_StackRef self, py_Name name) {
break; break;
case tp_classmethod: case tp_classmethod:
self[0] = *py_getslot(cls_var, 0); self[0] = *py_getslot(cls_var, 0);
self[1] = c11__getitem(py_TypeInfo, &pk_current_vm->types, type).self; self[1] = pk__type_info(type)->self;
break; break;
default: c11__unreachedable(); default: c11__unreachedable();
} }
@ -189,41 +190,40 @@ bool pk_loadmethod(py_StackRef self, py_Name name) {
py_Ref py_tpfindmagic(py_Type t, py_Name name) { py_Ref py_tpfindmagic(py_Type t, py_Name name) {
assert(py_ismagicname(name)); assert(py_ismagicname(name));
py_TypeInfo* types = (py_TypeInfo*)pk_current_vm->types.data; TypeList* types = &pk_current_vm->types;
do { do {
py_Ref f = &types[t].magic[name]; py_TypeInfo* ti = TypeList__get(types, t);
py_Ref f = &ti->magic[name];
if(!py_isnil(f)) return f; if(!py_isnil(f)) return f;
t = types[t].base; t = ti->base;
} while(t); } while(t);
return NULL; return NULL;
} }
py_Ref py_tpfindname(py_Type t, py_Name name) { py_Ref py_tpfindname(py_Type t, py_Name name) {
py_TypeInfo* types = (py_TypeInfo*)pk_current_vm->types.data; TypeList* types = &pk_current_vm->types;
do { do {
py_Ref res = py_getdict(&types[t].self, name); py_TypeInfo* ti = TypeList__get(types, t);
py_Ref res = py_getdict(&ti->self, name);
if(res) return res; if(res) return res;
t = types[t].base; t = ti->base;
} while(t); } while(t);
return NULL; return NULL;
} }
py_Ref py_tpgetmagic(py_Type type, py_Name name) { py_Ref py_tpgetmagic(py_Type type, py_Name name) {
assert(py_ismagicname(name)); assert(py_ismagicname(name));
VM* vm = pk_current_vm; return pk__type_info(type)->magic + name;
return &c11__at(py_TypeInfo, &vm->types, type)->magic[name];
} }
py_Ref py_tpobject(py_Type type) { py_Ref py_tpobject(py_Type type) {
assert(type); assert(type);
VM* vm = pk_current_vm; return &pk__type_info(type)->self;
return &c11__at(py_TypeInfo, &vm->types, type)->self;
} }
const char* py_tpname(py_Type type) { const char* py_tpname(py_Type type) {
if(!type) return "nil"; if(!type) return "nil";
VM* vm = pk_current_vm; py_Name name = pk__type_info(type)->name;
py_Name name = c11__at(py_TypeInfo, &vm->types, type)->name;
return py_name2str(name); return py_name2str(name);
} }

View File

@ -675,8 +675,7 @@ static bool super__new__(int argc, py_Ref argv) {
return TypeError("super() takes 0 or 2 arguments"); return TypeError("super() takes 0 or 2 arguments");
} }
py_TypeInfo* types = pk_current_vm->types.data; *class_arg = pk__type_info(*class_arg)->base;
*class_arg = types[*class_arg].base;
if(*class_arg == 0) return RuntimeError("super(): base class is invalid"); if(*class_arg == 0) return RuntimeError("super(): base class is invalid");
py_setslot(py_retval(), 0, self_arg); py_setslot(py_retval(), 0, self_arg);

View File

@ -5,7 +5,7 @@
bool pk__object_new(int argc, py_Ref argv) { bool pk__object_new(int argc, py_Ref argv) {
if(argc == 0) return TypeError("object.__new__(): not enough arguments"); if(argc == 0) return TypeError("object.__new__(): not enough arguments");
py_Type cls = py_totype(py_arg(0)); py_Type cls = py_totype(py_arg(0));
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, cls); py_TypeInfo* ti = pk__type_info(cls);
if(!ti->is_python) { if(!ti->is_python) {
return TypeError("object.__new__(%t) is not safe, use %t.__new__()", cls, cls); return TypeError("object.__new__(%t) is not safe, use %t.__new__()", cls, cls);
} }
@ -72,8 +72,7 @@ static bool type__new__(int argc, py_Ref argv) {
static bool type__base__(int argc, py_Ref argv) { static bool type__base__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
py_Type type = py_totype(argv); py_TypeInfo* ti = pk__type_info(py_totype(argv));
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
if(ti->base) { if(ti->base) {
py_assign(py_retval(), py_tpobject(ti->base)); py_assign(py_retval(), py_tpobject(ti->base));
} else { } else {
@ -84,8 +83,7 @@ static bool type__base__(int argc, py_Ref argv) {
static bool type__name__(int argc, py_Ref argv) { static bool type__name__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
py_Type type = py_totype(argv); py_TypeInfo* ti = pk__type_info(py_totype(argv));
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
py_newstr(py_retval(), py_name2str(ti->name)); py_newstr(py_retval(), py_name2str(ti->name));
return true; return true;
} }
@ -97,8 +95,7 @@ static bool type__getitem__(int argc, py_Ref argv) {
static bool type__module__(int argc, py_Ref argv) { static bool type__module__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
py_Type type = py_totype(argv); py_TypeInfo* ti = pk__type_info(py_totype(argv));
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
if(py_isnil(&ti->module)) { if(py_isnil(&ti->module)) {
py_newnone(py_retval()); py_newnone(py_retval());
} else { } else {
@ -110,8 +107,7 @@ static bool type__module__(int argc, py_Ref argv) {
static bool type__annotations__(int argc, py_Ref argv) { static bool type__annotations__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
py_Type type = py_totype(argv); py_TypeInfo* ti = pk__type_info(py_totype(argv));
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
if(py_isnil(&ti->annotations)) { if(py_isnil(&ti->annotations)) {
py_newdict(py_retval()); py_newdict(py_retval());
} else { } else {
@ -128,7 +124,7 @@ void pk_object__register() {
py_bindmagic(tp_object, __eq__, object__eq__); py_bindmagic(tp_object, __eq__, object__eq__);
py_bindmagic(tp_object, __ne__, object__ne__); py_bindmagic(tp_object, __ne__, object__ne__);
py_bindmagic(tp_object, __repr__, object__repr__); py_bindmagic(tp_object, __repr__, object__repr__);
py_bindmagic(tp_type, __repr__, type__repr__); py_bindmagic(tp_type, __repr__, type__repr__);
py_bindmagic(tp_type, __new__, type__new__); py_bindmagic(tp_type, __new__, type__new__);
py_bindmagic(tp_type, __getitem__, type__getitem__); py_bindmagic(tp_type, __getitem__, type__getitem__);

View File

@ -1,3 +1,4 @@
#include "pocketpy/interpreter/typeinfo.h"
#include "pocketpy/interpreter/vm.h" #include "pocketpy/interpreter/vm.h"
#include "pocketpy/objects/base.h" #include "pocketpy/objects/base.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
@ -45,11 +46,12 @@ int py_bool(py_Ref val) {
bool py_hash(py_Ref val, int64_t* out) { bool py_hash(py_Ref val, int64_t* out) {
py_Type t = val->type; py_Type t = val->type;
py_TypeInfo* types = (py_TypeInfo*)pk_current_vm->types.data; TypeList* types = &pk_current_vm->types;
do { do {
py_Ref _hash = &types[t].magic[__hash__]; py_TypeInfo* ti = TypeList__get(types, t);
py_Ref _hash = &ti->magic[__hash__];
if(py_isnone(_hash)) break; if(py_isnone(_hash)) break;
py_Ref _eq = &types[t].magic[__eq__]; py_Ref _eq = &ti->magic[__eq__];
if(!py_isnil(_eq)) { if(!py_isnil(_eq)) {
if(py_isnil(_hash)) break; if(py_isnil(_hash)) break;
if(!py_call(_hash, 1, val)) return false; if(!py_call(_hash, 1, val)) return false;
@ -57,7 +59,7 @@ bool py_hash(py_Ref val, int64_t* out) {
*out = py_toint(py_retval()); *out = py_toint(py_retval());
return true; return true;
} }
t = types[t].base; t = ti->base;
} while(t); } while(t);
return TypeError("unhashable type: '%t'", val->type); return TypeError("unhashable type: '%t'", val->type);
} }