mirror of
https://github.com/pocketpy/pocketpy
synced 2025-11-09 21:20:17 +00:00
Compare commits
3 Commits
a9955cd210
...
f530d8d111
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f530d8d111 | ||
|
|
8be90c3ba5 | ||
|
|
6b61c85dac |
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
typedef struct TraceInfo {
|
typedef struct TraceInfo {
|
||||||
SourceLocation prev_loc;
|
SourceLocation prev_loc;
|
||||||
py_TraceFunc tracefunc;
|
py_TraceFunc func;
|
||||||
} TraceInfo;
|
} TraceInfo;
|
||||||
|
|
||||||
typedef struct VM {
|
typedef struct VM {
|
||||||
@ -44,7 +44,7 @@ typedef struct VM {
|
|||||||
void* ctx; // user-defined context
|
void* ctx; // user-defined context
|
||||||
|
|
||||||
py_StackRef curr_class;
|
py_StackRef curr_class;
|
||||||
py_StackRef curr_function;
|
py_StackRef curr_decl_based_function;
|
||||||
TraceInfo trace_info;
|
TraceInfo trace_info;
|
||||||
py_TValue vectorcall_buffer[PK_MAX_CO_VARNAMES];
|
py_TValue vectorcall_buffer[PK_MAX_CO_VARNAMES];
|
||||||
|
|
||||||
|
|||||||
@ -55,9 +55,9 @@ typedef struct py_Frame py_Frame;
|
|||||||
// An enum for tracing events.
|
// An enum for tracing events.
|
||||||
enum py_TraceEvent {
|
enum py_TraceEvent {
|
||||||
TRACE_EVENT_LINE,
|
TRACE_EVENT_LINE,
|
||||||
TRACE_EVENT_CALL,
|
|
||||||
TRACE_EVENT_RETURN,
|
|
||||||
TRACE_EVENT_EXCEPTION,
|
TRACE_EVENT_EXCEPTION,
|
||||||
|
TRACE_EVENT_PUSH,
|
||||||
|
TRACE_EVENT_POP,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*py_TraceFunc)(py_Frame* frame, enum py_TraceEvent);
|
typedef void (*py_TraceFunc)(py_Frame* frame, enum py_TraceEvent);
|
||||||
@ -108,6 +108,12 @@ PK_API void py_sys_settrace(py_TraceFunc func);
|
|||||||
/// Setup the callbacks for the current VM.
|
/// Setup the callbacks for the current VM.
|
||||||
PK_API py_Callbacks* py_callbacks();
|
PK_API py_Callbacks* py_callbacks();
|
||||||
|
|
||||||
|
/// Get the current source location of the frame.
|
||||||
|
PK_API const char* py_Frame_sourceloc(py_Frame* frame, int* lineno);
|
||||||
|
/// Get the function object of the frame.
|
||||||
|
/// Returns `NULL` if not available.
|
||||||
|
PK_API py_StackRef py_Frame_function(py_Frame* frame);
|
||||||
|
|
||||||
/// Run a source string.
|
/// Run a source string.
|
||||||
/// @param source source string.
|
/// @param source source string.
|
||||||
/// @param filename filename (for error messages).
|
/// @param filename filename (for error messages).
|
||||||
@ -385,7 +391,9 @@ PK_API py_StackRef py_inspect_currentfunction();
|
|||||||
/// Get the current `module` object where the code is executed.
|
/// Get the current `module` object where the code is executed.
|
||||||
/// Return `NULL` if not available.
|
/// Return `NULL` if not available.
|
||||||
PK_API py_GlobalRef py_inspect_currentmodule();
|
PK_API py_GlobalRef py_inspect_currentmodule();
|
||||||
|
/// Get the current frame object.
|
||||||
|
/// Return `NULL` if not available.
|
||||||
|
PK_API py_Frame* py_inspect_currentframe();
|
||||||
/************* Bindings *************/
|
/************* Bindings *************/
|
||||||
|
|
||||||
/// Bind a function to the object via "decl-based" style.
|
/// Bind a function to the object via "decl-based" style.
|
||||||
|
|||||||
@ -66,13 +66,7 @@ static bool stack_format_object(VM* self, c11_sv spec);
|
|||||||
FrameResult res = VM__vectorcall(self, (argc), (kwargc), true); \
|
FrameResult res = VM__vectorcall(self, (argc), (kwargc), true); \
|
||||||
switch(res) { \
|
switch(res) { \
|
||||||
case RES_RETURN: PUSH(&self->last_retval); break; \
|
case RES_RETURN: PUSH(&self->last_retval); break; \
|
||||||
case RES_CALL: { \
|
case RES_CALL: frame = self->top_frame; goto __NEXT_FRAME; \
|
||||||
frame = self->top_frame; \
|
|
||||||
if(self->trace_info.tracefunc) { \
|
|
||||||
self->trace_info.tracefunc(frame, TRACE_EVENT_CALL); \
|
|
||||||
} \
|
|
||||||
goto __NEXT_FRAME; \
|
|
||||||
} \
|
|
||||||
case RES_ERROR: goto __ERROR; \
|
case RES_ERROR: goto __ERROR; \
|
||||||
default: c11__unreachable(); \
|
default: c11__unreachable(); \
|
||||||
} \
|
} \
|
||||||
@ -105,14 +99,14 @@ FrameResult VM__run_top_frame(VM* self) {
|
|||||||
__NEXT_STEP:
|
__NEXT_STEP:
|
||||||
byte = codes[frame->ip];
|
byte = codes[frame->ip];
|
||||||
|
|
||||||
if(self->trace_info.tracefunc) {
|
if(self->trace_info.func) {
|
||||||
SourceLocation loc = Frame__source_location(frame);
|
SourceLocation loc = Frame__source_location(frame);
|
||||||
SourceLocation prev_loc = self->trace_info.prev_loc;
|
SourceLocation prev_loc = self->trace_info.prev_loc;
|
||||||
if(loc.lineno != prev_loc.lineno || loc.src != prev_loc.src) {
|
if(loc.lineno != prev_loc.lineno || loc.src != prev_loc.src) {
|
||||||
if(prev_loc.src) PK_DECREF(prev_loc.src);
|
if(prev_loc.src) PK_DECREF(prev_loc.src);
|
||||||
PK_INCREF(loc.src);
|
PK_INCREF(loc.src);
|
||||||
self->trace_info.prev_loc = loc;
|
self->trace_info.prev_loc = loc;
|
||||||
self->trace_info.tracefunc(frame, TRACE_EVENT_LINE);
|
self->trace_info.func(frame, TRACE_EVENT_LINE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -757,9 +751,6 @@ FrameResult VM__run_top_frame(VM* self) {
|
|||||||
} else {
|
} else {
|
||||||
py_newnone(&self->last_retval);
|
py_newnone(&self->last_retval);
|
||||||
}
|
}
|
||||||
if(self->trace_info.tracefunc) {
|
|
||||||
self->trace_info.tracefunc(frame, TRACE_EVENT_RETURN);
|
|
||||||
}
|
|
||||||
VM__pop_frame(self);
|
VM__pop_frame(self);
|
||||||
if(frame == base_frame) { // [ frameBase<- ]
|
if(frame == base_frame) { // [ frameBase<- ]
|
||||||
return RES_RETURN;
|
return RES_RETURN;
|
||||||
@ -1459,7 +1450,7 @@ static bool stack_format_object(VM* self, c11_sv spec) {
|
|||||||
|
|
||||||
void py_sys_settrace(py_TraceFunc func) {
|
void py_sys_settrace(py_TraceFunc func) {
|
||||||
TraceInfo* info = &pk_current_vm->trace_info;
|
TraceInfo* info = &pk_current_vm->trace_info;
|
||||||
info->tracefunc = func;
|
info->func = func;
|
||||||
if(info->prev_loc.src) {
|
if(info->prev_loc.src) {
|
||||||
PK_DECREF(info->prev_loc.src);
|
PK_DECREF(info->prev_loc.src);
|
||||||
info->prev_loc.src = NULL;
|
info->prev_loc.src = NULL;
|
||||||
|
|||||||
@ -121,6 +121,7 @@ void Frame__gc_mark(py_Frame* self) {
|
|||||||
|
|
||||||
int Frame__lineno(const py_Frame* self) {
|
int Frame__lineno(const py_Frame* self) {
|
||||||
int ip = self->ip;
|
int ip = self->ip;
|
||||||
|
if(ip < 0) return 0;
|
||||||
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).lineno;
|
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).lineno;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,3 +182,15 @@ SourceLocation Frame__source_location(py_Frame* self) {
|
|||||||
loc.src = self->co->src;
|
loc.src = self->co->src;
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* py_Frame_sourceloc(py_Frame* self, int* lineno) {
|
||||||
|
SourceLocation loc = Frame__source_location(self);
|
||||||
|
*lineno = loc.lineno;
|
||||||
|
return loc.src->filename->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
py_StackRef py_Frame_function(py_Frame* self) {
|
||||||
|
if(self->is_locals_special) return NULL;
|
||||||
|
assert(self->p0->type == tp_function);
|
||||||
|
return self->p0;
|
||||||
|
}
|
||||||
@ -75,7 +75,7 @@ void VM__ctor(VM* self) {
|
|||||||
|
|
||||||
self->ctx = NULL;
|
self->ctx = NULL;
|
||||||
self->curr_class = NULL;
|
self->curr_class = NULL;
|
||||||
self->curr_function = NULL;
|
self->curr_decl_based_function = NULL;
|
||||||
memset(&self->trace_info, 0, sizeof(TraceInfo));
|
memset(&self->trace_info, 0, sizeof(TraceInfo));
|
||||||
|
|
||||||
FixedMemoryPool__ctor(&self->pool_frame, sizeof(py_Frame), 32);
|
FixedMemoryPool__ctor(&self->pool_frame, sizeof(py_Frame), 32);
|
||||||
@ -265,13 +265,14 @@ void VM__dtor(VM* self) {
|
|||||||
void VM__push_frame(VM* self, py_Frame* frame) {
|
void VM__push_frame(VM* self, py_Frame* frame) {
|
||||||
frame->f_back = self->top_frame;
|
frame->f_back = self->top_frame;
|
||||||
self->top_frame = frame;
|
self->top_frame = frame;
|
||||||
|
if(self->trace_info.func) self->trace_info.func(frame, TRACE_EVENT_PUSH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM__pop_frame(VM* self) {
|
void VM__pop_frame(VM* self) {
|
||||||
assert(self->top_frame);
|
assert(self->top_frame);
|
||||||
py_Frame* frame = self->top_frame;
|
py_Frame* frame = self->top_frame;
|
||||||
|
if(self->trace_info.func) self->trace_info.func(frame, TRACE_EVENT_POP);
|
||||||
// reset stack pointer
|
// reset stack pointer
|
||||||
|
|
||||||
self->stack.sp = frame->p0;
|
self->stack.sp = frame->p0;
|
||||||
// pop frame and delete
|
// pop frame and delete
|
||||||
self->top_frame = frame->f_back;
|
self->top_frame = frame->f_back;
|
||||||
@ -491,10 +492,10 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
|
|||||||
return opcall ? RES_CALL : VM__run_top_frame(self);
|
return opcall ? RES_CALL : VM__run_top_frame(self);
|
||||||
} else {
|
} else {
|
||||||
// decl-based binding
|
// decl-based binding
|
||||||
self->curr_function = p0;
|
self->curr_decl_based_function = p0;
|
||||||
bool ok = py_callcfunc(fn->cfunc, co->nlocals, argv);
|
bool ok = py_callcfunc(fn->cfunc, co->nlocals, argv);
|
||||||
self->stack.sp = p0;
|
self->stack.sp = p0;
|
||||||
self->curr_function = NULL;
|
self->curr_decl_based_function = NULL;
|
||||||
return ok ? RES_RETURN : RES_ERROR;
|
return ok ? RES_RETURN : RES_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -520,10 +521,10 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
|
|||||||
return opcall ? RES_CALL : VM__run_top_frame(self);
|
return opcall ? RES_CALL : VM__run_top_frame(self);
|
||||||
} else {
|
} else {
|
||||||
// decl-based binding
|
// decl-based binding
|
||||||
self->curr_function = p0;
|
self->curr_decl_based_function = p0;
|
||||||
bool ok = py_callcfunc(fn->cfunc, co->nlocals, argv);
|
bool ok = py_callcfunc(fn->cfunc, co->nlocals, argv);
|
||||||
self->stack.sp = p0;
|
self->stack.sp = p0;
|
||||||
self->curr_function = NULL;
|
self->curr_decl_based_function = NULL;
|
||||||
return ok ? RES_RETURN : RES_ERROR;
|
return ok ? RES_RETURN : RES_ERROR;
|
||||||
}
|
}
|
||||||
case FuncType_GENERATOR: {
|
case FuncType_GENERATOR: {
|
||||||
|
|||||||
@ -797,10 +797,34 @@ static bool function__doc__(int argc, py_Ref argv) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool function__name__(int argc, py_Ref argv) {
|
||||||
|
PY_CHECK_ARGC(1);
|
||||||
|
Function* func = py_touserdata(py_arg(0));
|
||||||
|
py_newstr(py_retval(), func->decl->code.name->data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool function__repr__(int argc, py_Ref argv) {
|
||||||
|
// <function f at 0x10365b9c0>
|
||||||
|
PY_CHECK_ARGC(1);
|
||||||
|
Function* func = py_touserdata(py_arg(0));
|
||||||
|
c11_sbuf buf;
|
||||||
|
c11_sbuf__ctor(&buf);
|
||||||
|
c11_sbuf__write_cstr(&buf, "<function ");
|
||||||
|
c11_sbuf__write_cstr(&buf, func->decl->code.name->data);
|
||||||
|
c11_sbuf__write_cstr(&buf, " at ");
|
||||||
|
c11_sbuf__write_ptr(&buf, func);
|
||||||
|
c11_sbuf__write_char(&buf, '>');
|
||||||
|
c11_sbuf__py_submit(&buf, py_retval());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
py_Type pk_function__register() {
|
py_Type pk_function__register() {
|
||||||
py_Type type =
|
py_Type type =
|
||||||
pk_newtype("function", tp_object, NULL, (void (*)(void*))Function__dtor, false, true);
|
pk_newtype("function", tp_object, NULL, (void (*)(void*))Function__dtor, false, true);
|
||||||
py_bindproperty(type, "__doc__", function__doc__, NULL);
|
py_bindproperty(type, "__doc__", function__doc__, NULL);
|
||||||
|
py_bindproperty(type, "__name__", function__name__, NULL);
|
||||||
|
py_bindmagic(type, __repr__, function__repr__);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -154,7 +154,7 @@ void py_clearexc(py_StackRef p0) {
|
|||||||
vm->is_curr_exc_handled = false;
|
vm->is_curr_exc_handled = false;
|
||||||
/* Don't clear this, because StopIteration() may corrupt the class definition */
|
/* Don't clear this, because StopIteration() may corrupt the class definition */
|
||||||
// vm->curr_class = NULL;
|
// vm->curr_class = NULL;
|
||||||
vm->curr_function = NULL;
|
vm->curr_decl_based_function = NULL;
|
||||||
if(p0) vm->stack.sp = p0;
|
if(p0) vm->stack.sp = p0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,9 +251,10 @@ bool py_raise(py_Ref exc) {
|
|||||||
}
|
}
|
||||||
vm->curr_exception = *exc;
|
vm->curr_exception = *exc;
|
||||||
vm->is_curr_exc_handled = false;
|
vm->is_curr_exc_handled = false;
|
||||||
if(vm->trace_info.tracefunc && !py_istype(exc, tp_StopIteration)) {
|
|
||||||
|
if(vm->trace_info.func && !py_istype(exc, tp_StopIteration)) {
|
||||||
py_Frame* frame = vm->top_frame;
|
py_Frame* frame = vm->top_frame;
|
||||||
vm->trace_info.tracefunc(frame, TRACE_EVENT_EXCEPTION);
|
vm->trace_info.func(frame, TRACE_EVENT_EXCEPTION);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,7 +69,11 @@ void py_setslot(py_Ref self, int i, py_Ref val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
py_StackRef py_inspect_currentfunction() {
|
py_StackRef py_inspect_currentfunction() {
|
||||||
return pk_current_vm->curr_function;
|
VM* vm = pk_current_vm;
|
||||||
|
if(vm->curr_decl_based_function) { return vm->curr_decl_based_function; }
|
||||||
|
py_Frame* frame = vm->top_frame;
|
||||||
|
if(!frame || frame->is_locals_special) return NULL;
|
||||||
|
return frame->p0;
|
||||||
}
|
}
|
||||||
|
|
||||||
py_GlobalRef py_inspect_currentmodule() {
|
py_GlobalRef py_inspect_currentmodule() {
|
||||||
@ -78,6 +82,8 @@ py_GlobalRef py_inspect_currentmodule(){
|
|||||||
return frame->module;
|
return frame->module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
py_Frame* py_inspect_currentframe() { return pk_current_vm->top_frame; }
|
||||||
|
|
||||||
void py_assign(py_Ref dst, py_Ref src) { *dst = *src; }
|
void py_assign(py_Ref dst, py_Ref src) { *dst = *src; }
|
||||||
|
|
||||||
/* Stack References */
|
/* Stack References */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user