mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
some refactor
This commit is contained in:
parent
02b27b66c5
commit
0f8c7d6d11
@ -4,10 +4,9 @@
|
||||
#include "pocketpy/common/vector.h"
|
||||
#include "pocketpy/objects/object.h"
|
||||
|
||||
#define PK_MAX_CHUNK_LENGTH 256
|
||||
|
||||
typedef struct py_TypeInfo {
|
||||
py_Name name;
|
||||
py_Type index;
|
||||
py_Type base;
|
||||
struct py_TypeInfo* base_ti;
|
||||
|
||||
@ -17,20 +16,13 @@ typedef struct py_TypeInfo {
|
||||
bool is_python; // is it a python class? (not derived from c object)
|
||||
bool is_sealed; // can it be subclassed?
|
||||
|
||||
void (*dtor)(void*);
|
||||
py_Dtor dtor; // destructor for this type, NULL if no dtor
|
||||
|
||||
py_TValue annotations;
|
||||
|
||||
void (*on_end_subclass)(struct py_TypeInfo*); // backdoor for enum module
|
||||
} py_TypeInfo;
|
||||
|
||||
typedef struct TypeList {
|
||||
int length;
|
||||
py_TypeInfo* chunks[PK_MAX_CHUNK_LENGTH];
|
||||
} 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);
|
||||
py_TypeInfo* pk_typeinfo(py_Type type);
|
||||
py_ItemRef pk_tpfindname(py_TypeInfo* ti, py_Name name);
|
||||
#define pk_tpfindmagic pk_tpfindname
|
@ -29,11 +29,16 @@ typedef struct WatchdogInfo {
|
||||
clock_t max_reset_time;
|
||||
} WatchdogInfo;
|
||||
|
||||
typedef struct TypePointer {
|
||||
py_TypeInfo* ti;
|
||||
py_Dtor dtor;
|
||||
} TypePointer;
|
||||
|
||||
typedef struct VM {
|
||||
py_Frame* top_frame;
|
||||
|
||||
BinTree modules;
|
||||
TypeList types;
|
||||
c11_vector /*TypePointer*/ types;
|
||||
|
||||
py_GlobalRef builtins; // builtins module
|
||||
py_GlobalRef main; // __main__ module
|
||||
@ -80,7 +85,7 @@ bool pk__parse_int_slice(py_Ref slice,
|
||||
bool pk__normalize_index(int* index, int length);
|
||||
|
||||
bool pk__object_new(int argc, py_Ref argv);
|
||||
py_TypeInfo* pk__type_info(py_Type type);
|
||||
py_TypeInfo* pk_typeinfo(py_Type type);
|
||||
|
||||
bool pk_wrapper__self(int argc, py_Ref argv);
|
||||
|
||||
|
@ -1036,7 +1036,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
POP();
|
||||
|
||||
py_TypeInfo* base_ti = TypeList__get(&self->types, base);
|
||||
py_TypeInfo* base_ti = pk_typeinfo(base);
|
||||
if(base_ti->is_sealed) {
|
||||
TypeError("type '%t' is not an acceptable base type", base);
|
||||
goto __ERROR;
|
||||
@ -1059,7 +1059,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
|
||||
if(py_istype(TOP(), tp_type)) {
|
||||
// call on_end_subclass
|
||||
py_TypeInfo* ti = TypeList__get(&self->types, py_totype(TOP()));
|
||||
py_TypeInfo* ti = py_touserdata(TOP());
|
||||
if(ti->base != tp_object) {
|
||||
py_TypeInfo* base_ti = ti->base_ti;
|
||||
if(base_ti->on_end_subclass) base_ti->on_end_subclass(ti);
|
||||
@ -1096,8 +1096,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
case OP_ADD_CLASS_ANNOTATION: {
|
||||
assert(self->curr_class);
|
||||
// [type_hint string]
|
||||
py_Type type = py_totype(self->curr_class);
|
||||
py_TypeInfo* ti = TypeList__get(&self->types, type);
|
||||
py_TypeInfo* ti = py_touserdata(self->curr_class);
|
||||
if(py_isnil(&ti->annotations)) py_newdict(&ti->annotations);
|
||||
py_Name name = co_names[byte.arg];
|
||||
bool ok = py_dict_setitem_by_str(&ti->annotations, py_name2str(name), TOP());
|
||||
|
@ -1,51 +1,49 @@
|
||||
#include "pocketpy/interpreter/typeinfo.h"
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
#define CHUNK_SIZE 128
|
||||
#define LOG2_CHUNK_SIZE 7
|
||||
|
||||
void TypeList__ctor(TypeList* self) {
|
||||
self->length = 0;
|
||||
memset(self->chunks, 0, sizeof(self->chunks));
|
||||
py_ItemRef pk_tpfindname(py_TypeInfo* ti, py_Name name) {
|
||||
assert(ti != NULL);
|
||||
do {
|
||||
py_Ref res = py_getdict(&ti->self, name);
|
||||
if(res) return res;
|
||||
ti = ti->base_ti;
|
||||
} while(ti);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void TypeList__dtor(TypeList* self) {
|
||||
for(py_Type t = 0; t < self->length; t++) {
|
||||
py_TypeInfo* info = TypeList__get(self, t);
|
||||
(void)info;
|
||||
}
|
||||
for(int i = 0; i < PK_MAX_CHUNK_LENGTH; i++) {
|
||||
if(self->chunks[i]) PK_FREE(self->chunks[i]);
|
||||
}
|
||||
py_ItemRef py_tpfindname(py_Type type, py_Name name) {
|
||||
py_TypeInfo* ti = pk_typeinfo(type);
|
||||
return pk_tpfindname(ti, name);
|
||||
}
|
||||
|
||||
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_Ref py_tpfindmagic(py_Type t, py_Name name) {
|
||||
// assert(py_ismagicname(name));
|
||||
return py_tpfindname(t, name);
|
||||
}
|
||||
|
||||
py_TypeInfo* TypeList__emplace(TypeList* self) {
|
||||
int chunk = self->length >> LOG2_CHUNK_SIZE;
|
||||
int offset = self->length & (CHUNK_SIZE - 1);
|
||||
if(self->chunks[chunk] == NULL) {
|
||||
if(chunk >= PK_MAX_CHUNK_LENGTH) {
|
||||
c11__abort("TypeList__emplace(): max chunk length exceeded");
|
||||
}
|
||||
self->chunks[chunk] = PK_MALLOC(sizeof(py_TypeInfo) * CHUNK_SIZE);
|
||||
memset(self->chunks[chunk], 0, sizeof(py_TypeInfo) * CHUNK_SIZE);
|
||||
}
|
||||
self->length++;
|
||||
return self->chunks[chunk] + offset;
|
||||
py_Type py_tpbase(py_Type t) {
|
||||
assert(t);
|
||||
py_TypeInfo* ti = pk_typeinfo(t);
|
||||
return ti->base;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
PK_DEPRECATED py_Ref py_tpgetmagic(py_Type type, py_Name name) {
|
||||
// assert(py_ismagicname(name));
|
||||
py_TypeInfo* ti = pk_typeinfo(type);
|
||||
py_Ref retval = py_getdict(&ti->self, name);
|
||||
return retval != NULL ? retval : py_NIL();
|
||||
}
|
||||
|
||||
#undef CHUNK_SIZE
|
||||
#undef LOG2_CHUNK_SIZE
|
||||
py_Ref py_tpobject(py_Type type) {
|
||||
assert(type);
|
||||
return &pk_typeinfo(type)->self;
|
||||
}
|
||||
|
||||
const char* py_tpname(py_Type type) {
|
||||
if(!type) return "nil";
|
||||
py_Name name = pk_typeinfo(type)->name;
|
||||
return py_name2str(name);
|
||||
}
|
||||
|
||||
py_TypeInfo* pk_typeinfo(py_Type type) {
|
||||
return c11__getitem(TypePointer, &pk_current_vm->types, type).ti;
|
||||
}
|
@ -39,40 +39,12 @@ void LineProfiler__tracefunc(py_Frame* frame, enum py_TraceEvent event) {
|
||||
if(self->enabled && event == TRACE_EVENT_LINE) { LineProfiler__tracefunc_line(self, frame); }
|
||||
}
|
||||
|
||||
static void py_TypeInfo__ctor(py_TypeInfo* self,
|
||||
py_Name name,
|
||||
py_Type index,
|
||||
py_Type base,
|
||||
py_TypeInfo* base_ti,
|
||||
py_GlobalRef module) {
|
||||
memset(self, 0, sizeof(py_TypeInfo));
|
||||
|
||||
self->name = name;
|
||||
self->base = base;
|
||||
self->base_ti = base_ti;
|
||||
|
||||
// create type object with __dict__
|
||||
ManagedHeap* heap = &pk_current_vm->heap;
|
||||
PyObject* typeobj = ManagedHeap__new(heap, tp_type, -1, sizeof(py_Type));
|
||||
*(py_Type*)PyObject__userdata(typeobj) = index;
|
||||
self->self = (py_TValue){
|
||||
.type = typeobj->type,
|
||||
.is_ptr = true,
|
||||
._obj = typeobj,
|
||||
};
|
||||
|
||||
self->module = module;
|
||||
self->annotations = *py_NIL();
|
||||
}
|
||||
|
||||
static int BinTree__cmp_cstr(void* lhs, void* rhs) {
|
||||
const char* l = (const char*)lhs;
|
||||
const char* r = (const char*)rhs;
|
||||
return strcmp(l, r);
|
||||
}
|
||||
|
||||
static int BinTree__cmp_voidp(void* lhs, void* rhs) { return lhs < rhs ? -1 : (lhs > rhs ? 1 : 0); }
|
||||
|
||||
void VM__ctor(VM* self) {
|
||||
self->top_frame = NULL;
|
||||
|
||||
@ -81,7 +53,7 @@ void VM__ctor(VM* self) {
|
||||
.need_free_key = true,
|
||||
};
|
||||
BinTree__ctor(&self->modules, c11_strdup(""), py_NIL(), &modules_config);
|
||||
TypeList__ctor(&self->types);
|
||||
c11_vector__ctor(&self->types, sizeof(TypePointer));
|
||||
|
||||
self->builtins = NULL;
|
||||
self->main = NULL;
|
||||
@ -116,14 +88,15 @@ void VM__ctor(VM* self) {
|
||||
|
||||
/* Init Builtin Types */
|
||||
// 0: unused
|
||||
void* placeholder = TypeList__emplace(&self->types);
|
||||
memset(placeholder, 0, sizeof(py_TypeInfo));
|
||||
TypePointer* placeholder = c11_vector__emplace(&self->types);
|
||||
placeholder->ti = NULL;
|
||||
placeholder->dtor = NULL;
|
||||
|
||||
#define validate(t, expr) \
|
||||
if(t != (expr)) abort()
|
||||
|
||||
validate(tp_object, pk_newtype("object", 0, NULL, NULL, true, false));
|
||||
validate(tp_type, pk_newtype("type", 1, NULL, NULL, false, true));
|
||||
validate(tp_object, pk_newtype("object", tp_nil, NULL, NULL, true, false));
|
||||
validate(tp_type, pk_newtype("type", tp_object, NULL, NULL, false, true));
|
||||
pk_object__register();
|
||||
|
||||
validate(tp_int, pk_newtype("int", tp_object, NULL, NULL, false, true));
|
||||
@ -229,7 +202,7 @@ void VM__ctor(VM* self) {
|
||||
};
|
||||
|
||||
for(int i = 0; i < c11__count_array(public_types); i++) {
|
||||
py_TypeInfo* ti = pk__type_info(public_types[i]);
|
||||
py_TypeInfo* ti = pk_typeinfo(public_types[i]);
|
||||
py_setdict(self->builtins, ti->name, &ti->self);
|
||||
}
|
||||
|
||||
@ -287,7 +260,7 @@ void VM__dtor(VM* self) {
|
||||
while(self->top_frame)
|
||||
VM__pop_frame(self);
|
||||
BinTree__dtor(&self->modules);
|
||||
TypeList__dtor(&self->types);
|
||||
c11_vector__dtor(&self->types);
|
||||
FixedMemoryPool__dtor(&self->pool_frame);
|
||||
ValueStack__dtor(&self->stack);
|
||||
CachedNames__dtor(&self->cached_names);
|
||||
@ -398,16 +371,30 @@ py_Type pk_newtype(const char* name,
|
||||
bool is_python,
|
||||
bool is_sealed) {
|
||||
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;
|
||||
py_TypeInfo* self = py_newobject(py_retval(), tp_type, -1, sizeof(py_TypeInfo));
|
||||
py_TypeInfo* base_ti = base ? pk_typeinfo(base) : NULL;
|
||||
if(base_ti && base_ti->is_sealed) {
|
||||
c11__abort("type '%s' is not an acceptable base type", py_name2str(base_ti->name));
|
||||
}
|
||||
py_TypeInfo__ctor(ti, py_name(name), index, base, base_ti, module ? module : py_NIL());
|
||||
|
||||
memset(self, 0, sizeof(py_TypeInfo));
|
||||
self->name = py_name(name);
|
||||
self->index = index;
|
||||
self->base = base;
|
||||
self->base_ti = base_ti;
|
||||
|
||||
self->self = *py_retval();
|
||||
self->module = module ? module : py_NIL();
|
||||
self->annotations = *py_NIL();
|
||||
|
||||
if(!dtor && base) dtor = base_ti->dtor;
|
||||
ti->dtor = dtor;
|
||||
ti->is_python = is_python;
|
||||
ti->is_sealed = is_sealed;
|
||||
self->is_python = is_python;
|
||||
self->is_sealed = is_sealed;
|
||||
self->dtor = dtor;
|
||||
|
||||
TypePointer* pointer = c11_vector__emplace(&pk_current_vm->types);
|
||||
pointer->ti = self;
|
||||
pointer->dtor = dtor;
|
||||
return index;
|
||||
}
|
||||
|
||||
@ -628,12 +615,6 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
|
||||
}
|
||||
|
||||
/****************************************/
|
||||
void PyObject__dtor(PyObject* self) {
|
||||
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));
|
||||
}
|
||||
|
||||
void FuncDecl__gc_mark(const FuncDecl* self, c11_vector* p_stack) {
|
||||
CodeObject__gc_mark(&self->code, p_stack);
|
||||
for(int j = 0; j < self->kwargs.length; j++) {
|
||||
@ -684,10 +665,8 @@ void ManagedHeap__mark(ManagedHeap* self) {
|
||||
int types_length = vm->types.length;
|
||||
// 0-th type is placeholder
|
||||
for(py_Type i = 1; i < types_length; i++) {
|
||||
py_TypeInfo* ti = TypeList__get(&vm->types, i);
|
||||
// mark type object
|
||||
py_TypeInfo* ti = c11__getitem(TypePointer, &vm->types, i).ti;
|
||||
pk__mark_value(&ti->self);
|
||||
// mark type annotations
|
||||
pk__mark_value(&ti->annotations);
|
||||
}
|
||||
// mark frame
|
||||
@ -763,125 +742,3 @@ void ManagedHeap__mark(ManagedHeap* self) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pk_print_stack(VM* self, py_Frame* frame, Bytecode byte) {
|
||||
return;
|
||||
if(frame == NULL || py_isnil(self->main)) return;
|
||||
|
||||
py_TValue* sp = self->stack.sp;
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
for(py_Ref p = self->stack.begin; p != sp; p++) {
|
||||
switch(p->type) {
|
||||
case tp_nil: c11_sbuf__write_cstr(&buf, "nil"); break;
|
||||
case tp_int: c11_sbuf__write_i64(&buf, p->_i64); break;
|
||||
case tp_float: c11_sbuf__write_f64(&buf, p->_f64, -1); break;
|
||||
case tp_bool: c11_sbuf__write_cstr(&buf, p->_bool ? "True" : "False"); break;
|
||||
case tp_NoneType: c11_sbuf__write_cstr(&buf, "None"); break;
|
||||
case tp_list: {
|
||||
pk_sprintf(&buf, "list(%d)", py_list_len(p));
|
||||
break;
|
||||
}
|
||||
case tp_tuple: {
|
||||
pk_sprintf(&buf, "tuple(%d)", py_tuple_len(p));
|
||||
break;
|
||||
}
|
||||
case tp_function: {
|
||||
Function* ud = py_touserdata(p);
|
||||
c11_sbuf__write_cstr(&buf, ud->decl->code.name->data);
|
||||
c11_sbuf__write_cstr(&buf, "()");
|
||||
break;
|
||||
}
|
||||
case tp_type: {
|
||||
pk_sprintf(&buf, "<class '%t'>", py_totype(p));
|
||||
break;
|
||||
}
|
||||
case tp_str: {
|
||||
pk_sprintf(&buf, "%q", py_tosv(p));
|
||||
break;
|
||||
}
|
||||
case tp_module: {
|
||||
py_Ref path = py_getdict(p, __path__);
|
||||
pk_sprintf(&buf, "<module '%v'>", py_tosv(path));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
pk_sprintf(&buf, "(%t)", p->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(p != &sp[-1]) c11_sbuf__write_cstr(&buf, ", ");
|
||||
}
|
||||
c11_string* stack_str = c11_sbuf__submit(&buf);
|
||||
|
||||
printf("%s:%-3d: %-25s %-6d [%s]\n",
|
||||
frame->co->src->filename->data,
|
||||
Frame__lineno(frame),
|
||||
pk_opname(byte.op),
|
||||
byte.arg,
|
||||
stack_str->data);
|
||||
c11_string__delete(stack_str);
|
||||
}
|
||||
|
||||
bool pk_wrapper__self(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_assign(py_retval(), argv);
|
||||
return true;
|
||||
}
|
||||
|
||||
py_TypeInfo* pk__type_info(py_Type type) { return TypeList__get(&pk_current_vm->types, type); }
|
||||
|
||||
int py_replinput(char* buf, int max_size) {
|
||||
buf[0] = '\0'; // reset first char because we check '@' at the beginning
|
||||
|
||||
int size = 0;
|
||||
bool multiline = false;
|
||||
printf(">>> ");
|
||||
|
||||
while(true) {
|
||||
int c = pk_current_vm->callbacks.getchr();
|
||||
if(c == EOF) return -1;
|
||||
|
||||
if(c == '\n') {
|
||||
char last = '\0';
|
||||
if(size > 0) last = buf[size - 1];
|
||||
if(multiline) {
|
||||
if(last == '\n') {
|
||||
break; // 2 consecutive newlines to end multiline input
|
||||
} else {
|
||||
printf("... ");
|
||||
}
|
||||
} else {
|
||||
if(last == ':' || last == '(' || last == '[' || last == '{' || buf[0] == '@') {
|
||||
printf("... ");
|
||||
multiline = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(size == max_size - 1) {
|
||||
buf[size] = '\0';
|
||||
return size;
|
||||
}
|
||||
|
||||
buf[size++] = c;
|
||||
}
|
||||
|
||||
buf[size] = '\0';
|
||||
return size;
|
||||
}
|
||||
|
||||
py_Ref py_name2ref(py_Name name) {
|
||||
assert(name != NULL);
|
||||
CachedNames* d = &pk_current_vm->cached_names;
|
||||
py_Ref res = CachedNames__try_get(d, name);
|
||||
if(res != NULL) return res;
|
||||
// not found, create a new one
|
||||
py_StackRef tmp = py_pushtmp();
|
||||
py_newstrv(tmp, py_name2sv(name));
|
||||
CachedNames__set(d, name, tmp);
|
||||
py_pop();
|
||||
return CachedNames__try_get(d, name);
|
||||
}
|
127
src/interpreter/vmx.c
Normal file
127
src/interpreter/vmx.c
Normal file
@ -0,0 +1,127 @@
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
void pk_print_stack(VM* self, py_Frame* frame, Bytecode byte) {
|
||||
return;
|
||||
if(frame == NULL || py_isnil(self->main)) return;
|
||||
|
||||
py_TValue* sp = self->stack.sp;
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
for(py_Ref p = self->stack.begin; p != sp; p++) {
|
||||
switch(p->type) {
|
||||
case tp_nil: c11_sbuf__write_cstr(&buf, "nil"); break;
|
||||
case tp_int: c11_sbuf__write_i64(&buf, p->_i64); break;
|
||||
case tp_float: c11_sbuf__write_f64(&buf, p->_f64, -1); break;
|
||||
case tp_bool: c11_sbuf__write_cstr(&buf, p->_bool ? "True" : "False"); break;
|
||||
case tp_NoneType: c11_sbuf__write_cstr(&buf, "None"); break;
|
||||
case tp_list: {
|
||||
pk_sprintf(&buf, "list(%d)", py_list_len(p));
|
||||
break;
|
||||
}
|
||||
case tp_tuple: {
|
||||
pk_sprintf(&buf, "tuple(%d)", py_tuple_len(p));
|
||||
break;
|
||||
}
|
||||
case tp_function: {
|
||||
Function* ud = py_touserdata(p);
|
||||
c11_sbuf__write_cstr(&buf, ud->decl->code.name->data);
|
||||
c11_sbuf__write_cstr(&buf, "()");
|
||||
break;
|
||||
}
|
||||
case tp_type: {
|
||||
pk_sprintf(&buf, "<class '%t'>", py_totype(p));
|
||||
break;
|
||||
}
|
||||
case tp_str: {
|
||||
pk_sprintf(&buf, "%q", py_tosv(p));
|
||||
break;
|
||||
}
|
||||
case tp_module: {
|
||||
py_Ref path = py_getdict(p, __path__);
|
||||
pk_sprintf(&buf, "<module '%v'>", py_tosv(path));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
pk_sprintf(&buf, "(%t)", p->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(p != &sp[-1]) c11_sbuf__write_cstr(&buf, ", ");
|
||||
}
|
||||
c11_string* stack_str = c11_sbuf__submit(&buf);
|
||||
|
||||
printf("%s:%-3d: %-25s %-6d [%s]\n",
|
||||
frame->co->src->filename->data,
|
||||
Frame__lineno(frame),
|
||||
pk_opname(byte.op),
|
||||
byte.arg,
|
||||
stack_str->data);
|
||||
c11_string__delete(stack_str);
|
||||
}
|
||||
|
||||
bool pk_wrapper__self(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_assign(py_retval(), argv);
|
||||
return true;
|
||||
}
|
||||
|
||||
int py_replinput(char* buf, int max_size) {
|
||||
buf[0] = '\0'; // reset first char because we check '@' at the beginning
|
||||
|
||||
int size = 0;
|
||||
bool multiline = false;
|
||||
printf(">>> ");
|
||||
|
||||
while(true) {
|
||||
int c = pk_current_vm->callbacks.getchr();
|
||||
if(c == EOF) return -1;
|
||||
|
||||
if(c == '\n') {
|
||||
char last = '\0';
|
||||
if(size > 0) last = buf[size - 1];
|
||||
if(multiline) {
|
||||
if(last == '\n') {
|
||||
break; // 2 consecutive newlines to end multiline input
|
||||
} else {
|
||||
printf("... ");
|
||||
}
|
||||
} else {
|
||||
if(last == ':' || last == '(' || last == '[' || last == '{' || buf[0] == '@') {
|
||||
printf("... ");
|
||||
multiline = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(size == max_size - 1) {
|
||||
buf[size] = '\0';
|
||||
return size;
|
||||
}
|
||||
|
||||
buf[size++] = c;
|
||||
}
|
||||
|
||||
buf[size] = '\0';
|
||||
return size;
|
||||
}
|
||||
|
||||
py_Ref py_name2ref(py_Name name) {
|
||||
assert(name != NULL);
|
||||
CachedNames* d = &pk_current_vm->cached_names;
|
||||
py_Ref res = CachedNames__try_get(d, name);
|
||||
if(res != NULL) return res;
|
||||
// not found, create a new one
|
||||
py_StackRef tmp = py_pushtmp();
|
||||
py_newstrv(tmp, py_name2sv(name));
|
||||
CachedNames__set(d, name, tmp);
|
||||
py_pop();
|
||||
return CachedNames__try_get(d, name);
|
||||
}
|
||||
|
||||
void PyObject__dtor(PyObject* self) {
|
||||
py_Dtor dtor = c11__getitem(TypePointer, &pk_current_vm->types, self->type).dtor;
|
||||
if(dtor) dtor(PyObject__userdata(self));
|
||||
if(self->slots == -1) NameDict__dtor(PyObject__dict(self));
|
||||
}
|
@ -86,5 +86,5 @@ void pk__add_module_enum() {
|
||||
py_bindproperty(type, "name", Enum__name, NULL);
|
||||
py_bindproperty(type, "value", Enum__value, NULL);
|
||||
|
||||
pk__type_info(type)->on_end_subclass = Enum__on_end_subclass;
|
||||
pk_typeinfo(type)->on_end_subclass = Enum__on_end_subclass;
|
||||
}
|
@ -61,7 +61,7 @@ static void PickleObject__write_bytes(PickleObject* buf, const void* data, int s
|
||||
}
|
||||
|
||||
static void c11_sbuf__write_type_path(c11_sbuf* path_buf, py_Type type) {
|
||||
py_TypeInfo* ti = pk__type_info(type);
|
||||
py_TypeInfo* ti = pk_typeinfo(type);
|
||||
if(py_isnil(ti->module)) {
|
||||
c11_sbuf__write_cstr(path_buf, py_name2str(ti->name));
|
||||
return;
|
||||
@ -349,7 +349,7 @@ static bool pkl__write_object(PickleObject* buf, py_TValue* obj) {
|
||||
// try memo for `is_ptr=true` objects
|
||||
if(pkl__try_memo(buf, obj->_obj)) return true;
|
||||
|
||||
py_TypeInfo* ti = pk__type_info(obj->type);
|
||||
py_TypeInfo* ti = pk_typeinfo(obj->type);
|
||||
py_Ref f_reduce = py_tpfindmagic(obj->type, __reduce__);
|
||||
if(f_reduce != NULL) {
|
||||
if(!py_call(f_reduce, 1, obj)) return false;
|
||||
|
@ -60,7 +60,7 @@ static bool pkpy_memory_usage(int argc, py_Ref argv) {
|
||||
static bool pkpy_is_user_defined_type(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_type);
|
||||
py_TypeInfo* ti = pk__type_info(py_totype(argv));
|
||||
py_TypeInfo* ti = py_touserdata(argv);
|
||||
py_newbool(py_retval(), ti->is_python);
|
||||
return true;
|
||||
}
|
||||
|
@ -45,49 +45,11 @@ bool py_tobool(py_Ref self) {
|
||||
|
||||
py_Type py_totype(py_Ref self) {
|
||||
assert(self->type == tp_type);
|
||||
py_Type* ud = py_touserdata(self);
|
||||
return *ud;
|
||||
py_TypeInfo* ud = py_touserdata(self);
|
||||
return ud->index;
|
||||
}
|
||||
|
||||
void* py_touserdata(py_Ref self) {
|
||||
assert(self && self->is_ptr);
|
||||
return PyObject__userdata(self->_obj);
|
||||
}
|
||||
|
||||
bool py_istype(py_Ref self, py_Type type) { return self->type == type; }
|
||||
|
||||
bool py_checktype(py_Ref self, py_Type type) {
|
||||
if(self->type == type) return true;
|
||||
return TypeError("expected '%t', got '%t'", type, self->type);
|
||||
}
|
||||
|
||||
bool py_checkinstance(py_Ref self, py_Type type) {
|
||||
if(py_isinstance(self, type)) return true;
|
||||
return TypeError("expected '%t' or its subclass, got '%t'", type, self->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) {
|
||||
TypeList* types = &pk_current_vm->types;
|
||||
do {
|
||||
if(derived == base) return true;
|
||||
derived = TypeList__get(types, derived)->base;
|
||||
} while(derived);
|
||||
return false;
|
||||
}
|
||||
|
||||
py_Type py_typeof(py_Ref self) { return self->type; }
|
||||
|
||||
py_Type py_gettype(const char* module, py_Name name) {
|
||||
py_Ref mod;
|
||||
if(module != NULL) {
|
||||
mod = py_getmodule(module);
|
||||
if(!mod) return 0;
|
||||
} else {
|
||||
mod = pk_current_vm->builtins;
|
||||
}
|
||||
py_Ref object = py_getdict(mod, name);
|
||||
if(object && py_istype(object, tp_type)) return py_totype(object);
|
||||
return 0;
|
||||
}
|
@ -238,7 +238,7 @@ bool pk_loadmethod(py_StackRef self, py_Name name) {
|
||||
break;
|
||||
case tp_classmethod:
|
||||
self[0] = *py_getslot(cls_var, 0);
|
||||
self[1] = pk__type_info(type)->self;
|
||||
self[1] = pk_typeinfo(type)->self;
|
||||
break;
|
||||
default: c11__unreachable();
|
||||
}
|
||||
@ -247,45 +247,6 @@ bool pk_loadmethod(py_StackRef self, py_Name name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
py_Ref py_tpfindmagic(py_Type t, py_Name name) {
|
||||
// assert(py_ismagicname(name));
|
||||
return py_tpfindname(t, name);
|
||||
}
|
||||
|
||||
py_Ref py_tpfindname(py_Type t, py_Name name) {
|
||||
py_TypeInfo* ti = pk__type_info(t);
|
||||
do {
|
||||
py_Ref res = py_getdict(&ti->self, name);
|
||||
if(res) return res;
|
||||
ti = ti->base_ti;
|
||||
} while(ti);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
py_Type py_tpbase(py_Type t) {
|
||||
assert(t);
|
||||
py_TypeInfo* ti = pk__type_info(t);
|
||||
return ti->base;
|
||||
}
|
||||
|
||||
PK_DEPRECATED py_Ref py_tpgetmagic(py_Type type, py_Name name) {
|
||||
// assert(py_ismagicname(name));
|
||||
py_TypeInfo* ti = pk__type_info(type);
|
||||
py_Ref retval = py_getdict(&ti->self, name);
|
||||
return retval != NULL ? retval : py_NIL();
|
||||
}
|
||||
|
||||
py_Ref py_tpobject(py_Type type) {
|
||||
assert(type);
|
||||
return &pk__type_info(type)->self;
|
||||
}
|
||||
|
||||
const char* py_tpname(py_Type type) {
|
||||
if(!type) return "nil";
|
||||
py_Name name = pk__type_info(type)->name;
|
||||
return py_name2str(name);
|
||||
}
|
||||
|
||||
bool py_tpcall(py_Type type, int argc, py_Ref argv) {
|
||||
return py_call(py_tpobject(type), argc, argv);
|
||||
}
|
||||
|
@ -843,7 +843,7 @@ static bool super__new__(int argc, py_Ref argv) {
|
||||
if(callable->type == tp_function) {
|
||||
Function* func = py_touserdata(callable);
|
||||
if(func->clazz != NULL) {
|
||||
class_arg = *(py_Type*)PyObject__userdata(func->clazz);
|
||||
class_arg = ((py_TypeInfo*)PyObject__userdata(func->clazz))->index;
|
||||
if(frame->co->nlocals > 0) { self_arg = &frame->locals[0]; }
|
||||
}
|
||||
}
|
||||
@ -851,7 +851,7 @@ static bool super__new__(int argc, py_Ref argv) {
|
||||
if(class_arg == 0 || self_arg == NULL) return RuntimeError("super(): no arguments");
|
||||
if(self_arg->type == tp_type) {
|
||||
// f(cls, ...)
|
||||
class_arg = pk__type_info(class_arg)->base;
|
||||
class_arg = pk_typeinfo(class_arg)->base;
|
||||
if(class_arg == 0) return RuntimeError("super(): base class is invalid");
|
||||
py_assign(py_retval(), py_tpobject(class_arg));
|
||||
return true;
|
||||
@ -868,7 +868,7 @@ static bool super__new__(int argc, py_Ref argv) {
|
||||
return TypeError("super() takes 0 or 2 arguments");
|
||||
}
|
||||
|
||||
class_arg = pk__type_info(class_arg)->base;
|
||||
class_arg = pk_typeinfo(class_arg)->base;
|
||||
if(class_arg == 0) return RuntimeError("super(): base class is invalid");
|
||||
|
||||
py_Type* p_class_arg = py_newobject(py_retval(), tp_super, 1, sizeof(py_Type));
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
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 = pk__type_info(cls);
|
||||
py_TypeInfo* ti = py_touserdata(argv);
|
||||
py_Type cls = ti->index;
|
||||
if(!ti->is_python) {
|
||||
return TypeError("object.__new__(%t) is not safe, use %t.__new__() instead", cls, cls);
|
||||
}
|
||||
@ -72,7 +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_TypeInfo* ti = pk__type_info(py_totype(argv));
|
||||
py_TypeInfo* ti = py_touserdata(argv);
|
||||
if(ti->base) {
|
||||
py_assign(py_retval(), &ti->base_ti->self);
|
||||
} else {
|
||||
@ -83,7 +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_TypeInfo* ti = pk__type_info(py_totype(argv));
|
||||
py_TypeInfo* ti = py_touserdata(argv);
|
||||
py_assign(py_retval(), py_name2ref(ti->name));
|
||||
return true;
|
||||
}
|
||||
@ -100,7 +100,7 @@ static bool type__or__(int argc, py_Ref argv) {
|
||||
|
||||
static bool type__module__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_TypeInfo* ti = pk__type_info(py_totype(argv));
|
||||
py_TypeInfo* ti = py_touserdata(argv);
|
||||
if(py_isnil(ti->module)) {
|
||||
py_newnone(py_retval());
|
||||
} else {
|
||||
@ -112,7 +112,7 @@ static bool type__module__(int argc, py_Ref argv) {
|
||||
|
||||
static bool type__annotations__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_TypeInfo* ti = pk__type_info(py_totype(argv));
|
||||
py_TypeInfo* ti = py_touserdata(argv);
|
||||
if(py_isnil(&ti->annotations)) {
|
||||
py_newdict(py_retval());
|
||||
} else {
|
||||
|
@ -52,7 +52,7 @@ int py_bool(py_Ref val) {
|
||||
}
|
||||
|
||||
bool py_hash(py_Ref val, int64_t* out) {
|
||||
py_TypeInfo* ti = pk__type_info(val->type);
|
||||
py_TypeInfo* ti = pk_typeinfo(val->type);
|
||||
do {
|
||||
py_Ref slot_hash = py_getdict(&ti->self, __hash__);
|
||||
if(slot_hash && py_isnone(slot_hash)) break;
|
||||
@ -93,8 +93,8 @@ int py_next(py_Ref val) {
|
||||
|
||||
bool py_getattr(py_Ref self, py_Name name) {
|
||||
// https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance
|
||||
py_Type type = self->type;
|
||||
py_Ref cls_var = py_tpfindname(type, name);
|
||||
py_TypeInfo* ti = pk_typeinfo(self->type);
|
||||
py_Ref cls_var = pk_tpfindname(ti, name);
|
||||
if(cls_var) {
|
||||
// handle descriptor
|
||||
if(py_istype(cls_var, tp_property)) {
|
||||
@ -111,8 +111,9 @@ bool py_getattr(py_Ref self, py_Name name) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
py_Type* inner_type = py_touserdata(self);
|
||||
py_Ref res = py_tpfindname(*inner_type, name);
|
||||
// self is a type object
|
||||
py_TypeInfo* inner_type = py_touserdata(self);
|
||||
py_Ref res = pk_tpfindname(inner_type, name);
|
||||
if(res) {
|
||||
if(py_istype(res, tp_staticmethod)) {
|
||||
res = py_getslot(res, 0);
|
||||
@ -145,7 +146,7 @@ bool py_getattr(py_Ref self, py_Name name) {
|
||||
return true;
|
||||
}
|
||||
case tp_classmethod: {
|
||||
py_newboundmethod(py_retval(), py_tpobject(type), py_getslot(cls_var, 0));
|
||||
py_newboundmethod(py_retval(), &ti->self, py_getslot(cls_var, 0));
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
@ -156,7 +157,7 @@ bool py_getattr(py_Ref self, py_Name name) {
|
||||
}
|
||||
}
|
||||
|
||||
py_Ref fallback = py_tpfindmagic(type, __getattr__);
|
||||
py_Ref fallback = pk_tpfindmagic(ti, __getattr__);
|
||||
if(fallback) {
|
||||
py_push(fallback);
|
||||
py_push(self);
|
||||
|
45
src/public/typecast.c
Normal file
45
src/public/typecast.c
Normal file
@ -0,0 +1,45 @@
|
||||
#include "pocketpy/objects/base.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
bool py_istype(py_Ref self, py_Type type) { return self->type == type; }
|
||||
|
||||
bool py_checktype(py_Ref self, py_Type type) {
|
||||
if(self->type == type) return true;
|
||||
return TypeError("expected '%t', got '%t'", type, self->type);
|
||||
}
|
||||
|
||||
bool py_checkinstance(py_Ref self, py_Type type) {
|
||||
if(py_isinstance(self, type)) return true;
|
||||
return TypeError("expected '%t' or its subclass, got '%t'", type, self->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) {
|
||||
assert(derived != 0 && base != 0);
|
||||
py_TypeInfo* derived_ti = pk_typeinfo(derived);
|
||||
py_TypeInfo* base_ti = pk_typeinfo(base);
|
||||
do {
|
||||
if(derived_ti == base_ti) return true;
|
||||
derived_ti = derived_ti->base_ti;
|
||||
} while(derived_ti);
|
||||
return false;
|
||||
}
|
||||
|
||||
py_Type py_typeof(py_Ref self) { return self->type; }
|
||||
|
||||
py_Type py_gettype(const char* module, py_Name name) {
|
||||
py_Ref mod;
|
||||
if(module != NULL) {
|
||||
mod = py_getmodule(module);
|
||||
if(!mod) return tp_nil;
|
||||
} else {
|
||||
mod = pk_current_vm->builtins;
|
||||
}
|
||||
py_Ref object = py_getdict(mod, name);
|
||||
if(object && py_istype(object, tp_type)) return py_totype(object);
|
||||
return tp_nil;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user