plan to implement tracefunc

This commit is contained in:
blueloveTH 2025-03-05 02:14:29 +08:00
parent 7b4994ee35
commit 19d0cfd4fd
7 changed files with 59 additions and 37 deletions

View File

@ -1,10 +1,10 @@
#pragma once
// clang-format off
#define PK_VERSION "2.0.6"
#define PK_VERSION "2.0.7"
#define PK_VERSION_MAJOR 2
#define PK_VERSION_MINOR 0
#define PK_VERSION_PATCH 6
#define PK_VERSION_PATCH 7
/*************** feature settings ***************/

View File

@ -33,7 +33,6 @@ typedef struct VM {
py_TValue last_retval;
py_TValue curr_exception;
volatile bool is_signal_interrupted;
bool is_curr_exc_handled; // handled by try-except block but not cleared yet
py_TValue reg[8]; // users' registers

View File

@ -34,6 +34,33 @@ 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.
@ -42,6 +69,8 @@ typedef struct py_Callbacks {
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
@ -89,8 +118,6 @@ PK_API void py_resetvm();
PK_API void* py_getvmctx();
/// Set the current VM context. This is used for user-defined data.
PK_API void py_setvmctx(void* ctx);
/// Interrupt the current VM and raise a `KeyboardInterrupt` exception.
PK_API void py_interrupt();
/// Set `sys.argv`. Used for storing command-line arguments.
PK_API void py_sys_setargv(int argc, char** argv);
/// Setup the callbacks for the current VM.
@ -219,10 +246,7 @@ PK_API c11_sv py_name2sv(py_Name);
/// @param base base type.
/// @param module module where the type is defined. Use `NULL` for built-in types.
/// @param dtor destructor function. Use `NULL` if not needed.
PK_API py_Type py_newtype(const char* name,
py_Type base,
const py_GlobalRef module,
py_Dtor dtor);
PK_API py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, py_Dtor dtor);
/// Create a new object.
/// @param out output reference.
@ -478,11 +502,10 @@ PK_API py_StackRef py_pushtmp();
/// If return false: `[self] -> [self]` (no change).
PK_API bool py_pushmethod(py_Name name);
/// Call a callable object via pocketpy's calling convention.
/// You need to prepare the stack using this form: `callable, self/nil, arg1, arg2, ..., k1, v1, k2, v2, ...`
/// `argc` is the number of positional arguments excluding `self`.
/// `kwargc` is the number of keyword arguments, i.e. the number of key-value pairs.
/// The result will be set to `py_retval()`.
/// The stack size will be reduced by `2 + argc + kwargc * 2`.
/// You need to prepare the stack using this form: `callable, self/nil, arg1, arg2, ..., k1, v1, k2,
/// v2, ...` `argc` is the number of positional arguments excluding `self`. `kwargc` is the number
/// of keyword arguments, i.e. the number of key-value pairs. The result will be set to
/// `py_retval()`. The stack size will be reduced by `2 + argc + kwargc * 2`.
PK_API bool py_vectorcall(uint16_t argc, uint16_t kwargc) PY_RAISE PY_RETURN;
/// Evaluate an expression and push the result to the stack.
/// This function is used for testing.
@ -536,7 +559,9 @@ PK_API void py_clearexc(py_StackRef p0);
#define AttributeError(self, n) \
py_exception(tp_AttributeError, "'%t' object has no attribute '%n'", (self)->type, (n))
#define UnboundLocalError(n) \
py_exception(tp_UnboundLocalError, "cannot access local variable '%n' where it is not associated with a value", (n))
py_exception(tp_UnboundLocalError, \
"cannot access local variable '%n' where it is not associated with a value", \
(n))
PK_API bool StopIteration() PY_RAISE;
PK_API bool KeyError(py_Ref key) PY_RAISE;
@ -672,15 +697,15 @@ PK_API int py_replinput(char* buf, int max_size);
/// %t: py_Type
/// %n: py_Name
enum py_MagicNames {
py_MagicNames__NULL, // 0 is reserved
enum py_MagicName {
py_MagicName__NULL, // 0 is reserved
#define MAGIC_METHOD(x) x,
#include "pocketpy/xmacros/magics.h"
#undef MAGIC_METHOD
};
enum py_PredefinedTypes {
enum py_PredefinedType {
tp_nil = 0,
tp_object = 1,
tp_type, // py_Type

View File

@ -97,18 +97,16 @@ FrameResult VM__run_top_frame(VM* self) {
frame->ip++;
__NEXT_STEP:
if(self->callbacks.tracefunc) {
// TODO: implement tracing mechanism
}
byte = codes[frame->ip];
#ifndef NDEBUG
pk_print_stack(self, frame, byte);
#endif
if(self->is_signal_interrupted) {
self->is_signal_interrupted = false;
py_exception(tp_KeyboardInterrupt, "");
goto __ERROR;
}
switch((Opcode)byte.op) {
case OP_NO_OP: DISPATCH();
/*****************************************/

View File

@ -68,10 +68,10 @@ 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_signal_interrupted = false;
self->is_curr_exc_handled = false;
self->ctx = NULL;

View File

@ -90,8 +90,6 @@ void* py_getvmctx() { return pk_current_vm->ctx; }
void py_setvmctx(void* ctx) { pk_current_vm->ctx = ctx; }
void py_interrupt() { pk_current_vm->is_signal_interrupted = true; }
void py_sys_setargv(int argc, char** argv) {
py_GlobalRef sys = py_getmodule("sys");
py_Ref argv_list = py_getdict(sys, py_name("argv"));

View File

@ -5,6 +5,8 @@
#include "pocketpy.h"
#define py_interrupt()
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>