blueloveTH 1 rok temu
rodzic
commit
64a4ae4676

+ 14 - 3
include/pocketpy/interpreter/vm.h

@@ -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;

+ 24 - 39
include/pocketpy/pocketpy.h

@@ -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();
 

+ 1 - 1
src/compiler/compiler.c

@@ -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;
     }
 

+ 11 - 11
src/interpreter/ceval.c

@@ -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());

+ 11 - 11
src/interpreter/vm.c

@@ -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

+ 2 - 2
src/public/py_exception.c

@@ -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;
 }
 

+ 1 - 1
src/public/stack_ops.c

@@ -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(){