mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 03:50:16 +00:00
...
This commit is contained in:
parent
f70d5af07f
commit
aaf7a84a3a
36
include/pocketpy/interpreter/typeinfo.h
Normal file
36
include/pocketpy/interpreter/typeinfo.h
Normal 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);
|
@ -5,6 +5,7 @@
|
||||
#include "pocketpy/interpreter/heap.h"
|
||||
#include "pocketpy/interpreter/frame.h"
|
||||
#include "pocketpy/interpreter/modules.h"
|
||||
#include "pocketpy/interpreter/typeinfo.h"
|
||||
|
||||
// TODO:
|
||||
// 1. __eq__ and __ne__ fallbacks
|
||||
@ -15,32 +16,11 @@
|
||||
// 6. py_TypeInfo
|
||||
// 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 {
|
||||
Frame* top_frame;
|
||||
|
||||
ModuleDict modules;
|
||||
c11_vector /*T=py_TypeInfo*/ types;
|
||||
TypeList types;
|
||||
|
||||
py_TValue builtins; // builtins module
|
||||
py_TValue main; // __main__ module
|
||||
@ -74,6 +54,7 @@ void pk__mark_value(py_TValue*);
|
||||
void pk__mark_namedict(NameDict*);
|
||||
void pk__tp_set_marker(py_Type type, void (*gc_mark)(void*));
|
||||
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__NotImplementedError(int argc, py_Ref argv);
|
||||
|
@ -24,4 +24,4 @@ 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);
|
||||
bool ModuleDict__contains(ModuleDict* self, const char* path);
|
||||
|
@ -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.
|
||||
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.
|
||||
/// 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.
|
||||
/// Return `NULL` if not found.
|
||||
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.
|
||||
PK_EXPORT py_ItemRef py_tpobject(py_Type type);
|
||||
PK_EXPORT py_GlobalRef py_tpobject(py_Type type);
|
||||
/// Get the type name.
|
||||
PK_EXPORT const char* py_tpname(py_Type type);
|
||||
/// Call a type to create a new instance.
|
||||
|
@ -871,7 +871,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
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) {
|
||||
TypeError("type '%t' is not an acceptable base type", base);
|
||||
goto __ERROR;
|
||||
@ -892,9 +892,9 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
|
||||
if(py_istype(TOP(), tp_type)) {
|
||||
// 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -915,7 +915,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
case OP_ADD_CLASS_ANNOTATION: {
|
||||
// [type_hint string]
|
||||
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);
|
||||
bool ok = py_dict_setitem_by_str(&ti->annotations, py_name2str(byte.arg), TOP());
|
||||
if(!ok) goto __ERROR;
|
||||
|
44
src/interpreter/typeinfo.c
Normal file
44
src/interpreter/typeinfo.c
Normal 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);
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/interpreter/generator.h"
|
||||
#include "pocketpy/interpreter/modules.h"
|
||||
#include "pocketpy/interpreter/typeinfo.h"
|
||||
#include "pocketpy/objects/base.h"
|
||||
#include "pocketpy/common/_generated.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
@ -56,7 +57,7 @@ void VM__ctor(VM* self) {
|
||||
self->top_frame = NULL;
|
||||
|
||||
ModuleDict__ctor(&self->modules, NULL, *py_NIL);
|
||||
c11_vector__ctor(&self->types, sizeof(py_TypeInfo));
|
||||
TypeList__ctor(&self->types);
|
||||
|
||||
self->builtins = *py_NIL;
|
||||
self->main = *py_NIL;
|
||||
@ -76,7 +77,7 @@ void VM__ctor(VM* self) {
|
||||
|
||||
/* Init Builtin Types */
|
||||
// 0: unused
|
||||
void* placeholder = c11_vector__emplace(&self->types);
|
||||
void* placeholder = TypeList__emplace(&self->types);
|
||||
memset(placeholder, 0, sizeof(py_TypeInfo));
|
||||
|
||||
#define validate(t, expr) \
|
||||
@ -187,7 +188,7 @@ void VM__ctor(VM* self) {
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -228,7 +229,7 @@ void VM__dtor(VM* self) {
|
||||
while(self->top_frame)
|
||||
VM__pop_frame(self);
|
||||
ModuleDict__dtor(&self->modules);
|
||||
c11_vector__dtor(&self->types);
|
||||
TypeList__dtor(&self->types);
|
||||
ValueStack__clear(&self->stack);
|
||||
}
|
||||
|
||||
@ -316,10 +317,9 @@ py_Type pk_newtype(const char* name,
|
||||
void (*dtor)(void*),
|
||||
bool is_python,
|
||||
bool is_sealed) {
|
||||
c11_vector* types = &pk_current_vm->types;
|
||||
py_Type index = types->length;
|
||||
py_TypeInfo* ti = c11_vector__emplace(types);
|
||||
py_TypeInfo* base_ti = base ? c11__at(py_TypeInfo, types, base) : NULL;
|
||||
py_Type index = pk_current_vm->types.length;
|
||||
py_TypeInfo* ti = TypeList__emplace(&pk_current_vm->types);
|
||||
py_TypeInfo* base_ti = base ? pk__type_info(base) : NULL;
|
||||
if(base_ti && base_ti->is_sealed) {
|
||||
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) {
|
||||
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(self->slots == -1) NameDict__dtor(PyObject__dict(self));
|
||||
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*)) {
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
|
||||
py_TypeInfo* ti = pk__type_info(type);
|
||||
assert(ti->gc_mark == NULL);
|
||||
ti->gc_mark = gc_mark;
|
||||
}
|
||||
@ -582,8 +582,8 @@ static void mark_object(PyObject* obj) {
|
||||
pk__mark_namedict(dict);
|
||||
}
|
||||
|
||||
py_TypeInfo* types = c11__at(py_TypeInfo, &pk_current_vm->types, obj->type);
|
||||
if(types->gc_mark) types->gc_mark(PyObject__userdata(obj));
|
||||
py_TypeInfo* ti = pk__type_info(obj->type);
|
||||
if(ti->gc_mark) ti->gc_mark(PyObject__userdata(obj));
|
||||
}
|
||||
|
||||
void CodeObject__gc_mark(const CodeObject* self) {
|
||||
@ -603,18 +603,18 @@ void ManagedHeap__mark(ManagedHeap* self) {
|
||||
pk__mark_value(p);
|
||||
}
|
||||
// mark types
|
||||
py_TypeInfo* types = vm->types.data;
|
||||
int types_length = vm->types.length;
|
||||
// 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
|
||||
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;
|
||||
pk__mark_value(slot);
|
||||
}
|
||||
// mark type annotations
|
||||
pk__mark_value(&types[i].annotations);
|
||||
pk__mark_value(&ti->annotations);
|
||||
}
|
||||
// mark frame
|
||||
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) {
|
||||
return py_exception(tp_NotImplementedError, "");
|
||||
}
|
||||
}
|
||||
|
||||
py_TypeInfo* pk__type_info(py_Type type) {
|
||||
return TypeList__get(&pk_current_vm->types, type);
|
||||
}
|
||||
|
@ -86,6 +86,6 @@ void pk__add_module_enum() {
|
||||
py_bindproperty(type, "name", Enum__name, 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;
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
#include "pocketpy/common/str.h"
|
||||
#include "pocketpy/objects/base.h"
|
||||
#include "pocketpy/pocketpy.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_issubclass(py_Type derived, py_Type base) {
|
||||
py_TypeInfo* types = pk_current_vm->types.data;
|
||||
TypeList* types = &pk_current_vm->types;
|
||||
do {
|
||||
if(derived == base) return true;
|
||||
derived = types[derived].base;
|
||||
derived = TypeList__get(types, derived)->base;
|
||||
} while(derived);
|
||||
return false;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "pocketpy/interpreter/typeinfo.h"
|
||||
#include "pocketpy/objects/codeobject.h"
|
||||
#include "pocketpy/objects/sourcedata.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
@ -178,7 +179,7 @@ bool pk_loadmethod(py_StackRef self, py_Name name) {
|
||||
break;
|
||||
case tp_classmethod:
|
||||
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;
|
||||
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) {
|
||||
assert(py_ismagicname(name));
|
||||
py_TypeInfo* types = (py_TypeInfo*)pk_current_vm->types.data;
|
||||
TypeList* types = &pk_current_vm->types;
|
||||
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;
|
||||
t = types[t].base;
|
||||
t = ti->base;
|
||||
} while(t);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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 {
|
||||
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;
|
||||
t = types[t].base;
|
||||
t = ti->base;
|
||||
} while(t);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
py_Ref py_tpgetmagic(py_Type type, py_Name name) {
|
||||
assert(py_ismagicname(name));
|
||||
VM* vm = pk_current_vm;
|
||||
return &c11__at(py_TypeInfo, &vm->types, type)->magic[name];
|
||||
return pk__type_info(type)->magic + name;
|
||||
}
|
||||
|
||||
py_Ref py_tpobject(py_Type type) {
|
||||
assert(type);
|
||||
VM* vm = pk_current_vm;
|
||||
return &c11__at(py_TypeInfo, &vm->types, type)->self;
|
||||
return &pk__type_info(type)->self;
|
||||
}
|
||||
|
||||
const char* py_tpname(py_Type type) {
|
||||
if(!type) return "nil";
|
||||
VM* vm = pk_current_vm;
|
||||
py_Name name = c11__at(py_TypeInfo, &vm->types, type)->name;
|
||||
py_Name name = pk__type_info(type)->name;
|
||||
return py_name2str(name);
|
||||
}
|
||||
|
||||
|
@ -675,8 +675,7 @@ static bool super__new__(int argc, py_Ref argv) {
|
||||
return TypeError("super() takes 0 or 2 arguments");
|
||||
}
|
||||
|
||||
py_TypeInfo* types = pk_current_vm->types.data;
|
||||
*class_arg = types[*class_arg].base;
|
||||
*class_arg = pk__type_info(*class_arg)->base;
|
||||
if(*class_arg == 0) return RuntimeError("super(): base class is invalid");
|
||||
|
||||
py_setslot(py_retval(), 0, self_arg);
|
||||
|
@ -5,7 +5,7 @@
|
||||
bool pk__object_new(int argc, py_Ref argv) {
|
||||
if(argc == 0) return TypeError("object.__new__(): not enough arguments");
|
||||
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) {
|
||||
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) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_Type type = py_totype(argv);
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
|
||||
py_TypeInfo* ti = pk__type_info(py_totype(argv));
|
||||
if(ti->base) {
|
||||
py_assign(py_retval(), py_tpobject(ti->base));
|
||||
} else {
|
||||
@ -84,8 +83,7 @@ static bool type__base__(int argc, py_Ref argv) {
|
||||
|
||||
static bool type__name__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_Type type = py_totype(argv);
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
|
||||
py_TypeInfo* ti = pk__type_info(py_totype(argv));
|
||||
py_newstr(py_retval(), py_name2str(ti->name));
|
||||
return true;
|
||||
}
|
||||
@ -97,8 +95,7 @@ static bool type__getitem__(int argc, py_Ref argv) {
|
||||
|
||||
static bool type__module__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_Type type = py_totype(argv);
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
|
||||
py_TypeInfo* ti = pk__type_info(py_totype(argv));
|
||||
if(py_isnil(&ti->module)) {
|
||||
py_newnone(py_retval());
|
||||
} else {
|
||||
@ -110,8 +107,7 @@ static bool type__module__(int argc, py_Ref argv) {
|
||||
|
||||
static bool type__annotations__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_Type type = py_totype(argv);
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
|
||||
py_TypeInfo* ti = pk__type_info(py_totype(argv));
|
||||
if(py_isnil(&ti->annotations)) {
|
||||
py_newdict(py_retval());
|
||||
} else {
|
||||
@ -128,7 +124,7 @@ void pk_object__register() {
|
||||
py_bindmagic(tp_object, __eq__, object__eq__);
|
||||
py_bindmagic(tp_object, __ne__, object__ne__);
|
||||
py_bindmagic(tp_object, __repr__, object__repr__);
|
||||
|
||||
|
||||
py_bindmagic(tp_type, __repr__, type__repr__);
|
||||
py_bindmagic(tp_type, __new__, type__new__);
|
||||
py_bindmagic(tp_type, __getitem__, type__getitem__);
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "pocketpy/interpreter/typeinfo.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
#include "pocketpy/objects/base.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
@ -45,11 +46,12 @@ int py_bool(py_Ref val) {
|
||||
|
||||
bool py_hash(py_Ref val, int64_t* out) {
|
||||
py_Type t = val->type;
|
||||
py_TypeInfo* types = (py_TypeInfo*)pk_current_vm->types.data;
|
||||
TypeList* types = &pk_current_vm->types;
|
||||
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;
|
||||
py_Ref _eq = &types[t].magic[__eq__];
|
||||
py_Ref _eq = &ti->magic[__eq__];
|
||||
if(!py_isnil(_eq)) {
|
||||
if(py_isnil(_hash)) break;
|
||||
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());
|
||||
return true;
|
||||
}
|
||||
t = types[t].base;
|
||||
t = ti->base;
|
||||
} while(t);
|
||||
return TypeError("unhashable type: '%t'", val->type);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user