mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 12:00:18 +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/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);
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
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/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) {
|
||||||
@ -696,3 +696,7 @@ 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);
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user