mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
add TraceInfo
This commit is contained in:
parent
46f9e4ed4f
commit
64a4ae4676
@ -18,6 +18,16 @@
|
||||
// 5. stack effect of each opcode
|
||||
// 6. py_TypeInfo
|
||||
|
||||
typedef struct SourceLocation {
|
||||
SourceData_ src;
|
||||
int lineno;
|
||||
} SourceLocation;
|
||||
|
||||
typedef struct TraceInfo {
|
||||
SourceLocation prev_loc;
|
||||
py_TraceFunc tracefunc;
|
||||
} TraceInfo;
|
||||
|
||||
typedef struct VM {
|
||||
Frame* top_frame;
|
||||
|
||||
@ -38,9 +48,10 @@ typedef struct VM {
|
||||
py_TValue reg[8]; // users' registers
|
||||
void* ctx; // user-defined context
|
||||
|
||||
py_StackRef __curr_class;
|
||||
py_StackRef __curr_function;
|
||||
py_TValue __vectorcall_buffer[PK_MAX_CO_VARNAMES];
|
||||
py_StackRef curr_class;
|
||||
py_StackRef curr_function;
|
||||
TraceInfo trace_info;
|
||||
py_TValue vectorcall_buffer[PK_MAX_CO_VARNAMES];
|
||||
|
||||
InternedNames names;
|
||||
FixedMemoryPool pool_frame;
|
||||
|
@ -34,45 +34,6 @@ typedef struct c11_sv {
|
||||
int size;
|
||||
} c11_sv;
|
||||
|
||||
// An enum for tracing events.
|
||||
enum py_TraceEvent {
|
||||
TraceEvent_Line,
|
||||
TraceEvent_Call,
|
||||
TraceEvent_Return,
|
||||
TraceEvent_Exception,
|
||||
};
|
||||
|
||||
/// A struct contains the arguments of the tracing event.
|
||||
union py_TraceEventArg {
|
||||
struct {
|
||||
int _;
|
||||
} line;
|
||||
|
||||
struct {
|
||||
int _;
|
||||
} call;
|
||||
|
||||
struct {
|
||||
int _;
|
||||
} return_;
|
||||
|
||||
struct {
|
||||
int _;
|
||||
} exception;
|
||||
};
|
||||
|
||||
/// A struct contains the callbacks of the VM.
|
||||
typedef struct py_Callbacks {
|
||||
/// Used by `__import__` to load source code of a module.
|
||||
char* (*importfile)(const char*);
|
||||
/// Used by `print` to output a string.
|
||||
void (*print)(const char*);
|
||||
/// Used by `input` to get a character.
|
||||
int (*getchar)();
|
||||
/// C-style `sys.settrace` function.
|
||||
void (*tracefunc)(enum py_TraceEvent, union py_TraceEventArg);
|
||||
} py_Callbacks;
|
||||
|
||||
#define PY_RAISE
|
||||
#define PY_RETURN
|
||||
|
||||
@ -89,6 +50,28 @@ typedef py_TValue* py_ItemRef;
|
||||
/// An output reference for returning a value.
|
||||
typedef py_TValue* py_OutRef;
|
||||
|
||||
typedef struct py_Frame py_Frame;
|
||||
|
||||
// An enum for tracing events.
|
||||
enum py_TraceEvent {
|
||||
TRACE_EVENT_LINE,
|
||||
TRACE_EVENT_CALL,
|
||||
TRACE_EVENT_RETURN,
|
||||
TRACE_EVENT_EXCEPTION,
|
||||
};
|
||||
|
||||
typedef void (*py_TraceFunc)(py_Frame* frame, enum py_TraceEvent);
|
||||
|
||||
/// A struct contains the callbacks of the VM.
|
||||
typedef struct py_Callbacks {
|
||||
/// Used by `__import__` to load source code of a module.
|
||||
char* (*importfile)(const char*);
|
||||
/// Used by `print` to output a string.
|
||||
void (*print)(const char*);
|
||||
/// Used by `input` to get a character.
|
||||
int (*getchar)();
|
||||
} py_Callbacks;
|
||||
|
||||
/// Native function signature.
|
||||
/// @param argc number of arguments.
|
||||
/// @param argv array of arguments. Use `py_arg(i)` macro to get the i-th argument.
|
||||
@ -120,6 +103,8 @@ PK_API void* py_getvmctx();
|
||||
PK_API void py_setvmctx(void* ctx);
|
||||
/// Set `sys.argv`. Used for storing command-line arguments.
|
||||
PK_API void py_sys_setargv(int argc, char** argv);
|
||||
/// Set the trace function for the current VM.
|
||||
PK_API void py_sys_settrace(py_TraceFunc func);
|
||||
/// Setup the callbacks for the current VM.
|
||||
PK_API py_Callbacks* py_callbacks();
|
||||
|
||||
|
@ -1046,7 +1046,7 @@ void CallExpr__emit_(Expr* self_, Ctx* ctx) {
|
||||
Opcode opcode = OP_CALL;
|
||||
if(vargs || vkwargs) {
|
||||
// in this case, there is at least one *args or **kwargs as StarredExpr
|
||||
// OP_CALL_VARGS needs to unpack them via __vectorcall_buffer
|
||||
// OP_CALL_VARGS needs to unpack them via vectorcall_buffer
|
||||
opcode = OP_CALL_VARGS;
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
frame->ip++;
|
||||
|
||||
__NEXT_STEP:
|
||||
if(self->callbacks.tracefunc) {
|
||||
if(self->trace_info.tracefunc) {
|
||||
// TODO: implement tracing mechanism
|
||||
}
|
||||
|
||||
@ -298,9 +298,9 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_LOAD_CLASS_GLOBAL: {
|
||||
assert(self->__curr_class);
|
||||
assert(self->curr_class);
|
||||
py_Name name = byte.arg;
|
||||
py_Ref tmp = py_getdict(self->__curr_class, name);
|
||||
py_Ref tmp = py_getdict(self->curr_class, name);
|
||||
if(tmp) {
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
@ -691,7 +691,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
py_TValue* sp = SP();
|
||||
py_TValue* p1 = sp - kwargc * 2;
|
||||
py_TValue* base = p1 - argc;
|
||||
py_TValue* buf = self->__vectorcall_buffer;
|
||||
py_TValue* buf = self->vectorcall_buffer;
|
||||
|
||||
for(py_TValue* curr = base; curr != p1; curr++) {
|
||||
if(curr->type != tp_star_wrapper) {
|
||||
@ -1008,7 +1008,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
base_ti->is_python,
|
||||
false);
|
||||
PUSH(py_tpobject(type));
|
||||
self->__curr_class = TOP();
|
||||
self->curr_class = TOP();
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_END_CLASS: {
|
||||
@ -1033,11 +1033,11 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
// class with decorator is unsafe currently
|
||||
// it skips the above check
|
||||
POP();
|
||||
self->__curr_class = NULL;
|
||||
self->curr_class = NULL;
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_STORE_CLASS_ATTR: {
|
||||
assert(self->__curr_class);
|
||||
assert(self->curr_class);
|
||||
py_Name name = byte.arg;
|
||||
// TOP() can be a function, classmethod or custom decorator
|
||||
py_Ref actual_func = TOP();
|
||||
@ -1046,16 +1046,16 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
if(actual_func->type == tp_function) {
|
||||
Function* ud = py_touserdata(actual_func);
|
||||
ud->clazz = self->__curr_class->_obj;
|
||||
ud->clazz = self->curr_class->_obj;
|
||||
}
|
||||
py_setdict(self->__curr_class, name, TOP());
|
||||
py_setdict(self->curr_class, name, TOP());
|
||||
POP();
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_ADD_CLASS_ANNOTATION: {
|
||||
assert(self->__curr_class);
|
||||
assert(self->curr_class);
|
||||
// [type_hint string]
|
||||
py_Type type = py_totype(self->__curr_class);
|
||||
py_Type type = py_totype(self->curr_class);
|
||||
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());
|
||||
|
@ -68,15 +68,15 @@ void VM__ctor(VM* self) {
|
||||
self->callbacks.importfile = pk_default_importfile;
|
||||
self->callbacks.print = pk_default_print;
|
||||
self->callbacks.getchar = getchar;
|
||||
self->callbacks.tracefunc = NULL;
|
||||
|
||||
self->last_retval = *py_NIL();
|
||||
self->curr_exception = *py_NIL();
|
||||
self->is_curr_exc_handled = false;
|
||||
|
||||
self->ctx = NULL;
|
||||
self->__curr_class = NULL;
|
||||
self->__curr_function = NULL;
|
||||
self->curr_class = NULL;
|
||||
self->curr_function = NULL;
|
||||
memset(&self->trace_info, 0, sizeof(TraceInfo));
|
||||
|
||||
FixedMemoryPool__ctor(&self->pool_frame, sizeof(Frame), 32);
|
||||
|
||||
@ -479,11 +479,11 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
|
||||
|
||||
switch(fn->decl->type) {
|
||||
case FuncType_NORMAL: {
|
||||
bool ok = prepare_py_call(self->__vectorcall_buffer, argv, p1, kwargc, fn->decl);
|
||||
bool ok = prepare_py_call(self->vectorcall_buffer, argv, p1, kwargc, fn->decl);
|
||||
if(!ok) return RES_ERROR;
|
||||
// copy buffer back to stack
|
||||
self->stack.sp = argv + co->nlocals;
|
||||
memcpy(argv, self->__vectorcall_buffer, co->nlocals * sizeof(py_TValue));
|
||||
memcpy(argv, self->vectorcall_buffer, co->nlocals * sizeof(py_TValue));
|
||||
// submit the call
|
||||
if(!fn->cfunc) {
|
||||
// python function
|
||||
@ -491,10 +491,10 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
|
||||
return opcall ? RES_CALL : VM__run_top_frame(self);
|
||||
} else {
|
||||
// decl-based binding
|
||||
self->__curr_function = p0;
|
||||
self->curr_function = p0;
|
||||
bool ok = py_callcfunc(fn->cfunc, co->nlocals, argv);
|
||||
self->stack.sp = p0;
|
||||
self->__curr_function = NULL;
|
||||
self->curr_function = NULL;
|
||||
return ok ? RES_RETURN : RES_ERROR;
|
||||
}
|
||||
}
|
||||
@ -520,18 +520,18 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
|
||||
return opcall ? RES_CALL : VM__run_top_frame(self);
|
||||
} else {
|
||||
// decl-based binding
|
||||
self->__curr_function = p0;
|
||||
self->curr_function = p0;
|
||||
bool ok = py_callcfunc(fn->cfunc, co->nlocals, argv);
|
||||
self->stack.sp = p0;
|
||||
self->__curr_function = NULL;
|
||||
self->curr_function = NULL;
|
||||
return ok ? RES_RETURN : RES_ERROR;
|
||||
}
|
||||
case FuncType_GENERATOR: {
|
||||
bool ok = prepare_py_call(self->__vectorcall_buffer, argv, p1, kwargc, fn->decl);
|
||||
bool ok = prepare_py_call(self->vectorcall_buffer, argv, p1, kwargc, fn->decl);
|
||||
if(!ok) return RES_ERROR;
|
||||
// copy buffer back to stack
|
||||
self->stack.sp = argv + co->nlocals;
|
||||
memcpy(argv, self->__vectorcall_buffer, co->nlocals * sizeof(py_TValue));
|
||||
memcpy(argv, self->vectorcall_buffer, co->nlocals * sizeof(py_TValue));
|
||||
Frame* frame = Frame__new(co, p0, fn->module, fn->globals, argv, false);
|
||||
pk_newgenerator(py_retval(), frame, p0, self->stack.sp);
|
||||
self->stack.sp = p0; // reset the stack
|
||||
|
@ -154,8 +154,8 @@ void py_clearexc(py_StackRef p0) {
|
||||
vm->curr_exception = *py_NIL();
|
||||
vm->is_curr_exc_handled = false;
|
||||
/* Don't clear this, because StopIteration() may corrupt the class definition */
|
||||
// vm->__curr_class = NULL;
|
||||
vm->__curr_function = NULL;
|
||||
// vm->curr_class = NULL;
|
||||
vm->curr_function = NULL;
|
||||
if(p0) vm->stack.sp = p0;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ void py_setslot(py_Ref self, int i, py_Ref val) {
|
||||
}
|
||||
|
||||
py_StackRef py_inspect_currentfunction(){
|
||||
return pk_current_vm->__curr_function;
|
||||
return pk_current_vm->curr_function;
|
||||
}
|
||||
|
||||
py_GlobalRef py_inspect_currentmodule(){
|
||||
|
Loading…
x
Reference in New Issue
Block a user