blueloveTH 1 anno fa
parent
commit
8be90c3ba5

+ 1 - 1
include/pocketpy/interpreter/vm.h

@@ -44,7 +44,7 @@ typedef struct VM {
     void* ctx;         // user-defined context
 
     py_StackRef curr_class;
-    py_StackRef curr_function;
+    py_StackRef curr_decl_based_function;
     TraceInfo trace_info;
     py_TValue vectorcall_buffer[PK_MAX_CO_VARNAMES];
 

+ 6 - 1
include/pocketpy/pocketpy.h

@@ -110,6 +110,9 @@ 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.
 /// @param source source string.
@@ -388,7 +391,9 @@ PK_API py_StackRef py_inspect_currentfunction();
 /// Get the current `module` object where the code is executed.
 /// Return `NULL` if not available.
 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 *************/
 
 /// Bind a function to the object via "decl-based" style.

+ 6 - 0
src/interpreter/frame.c

@@ -187,4 +187,10 @@ 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;
 }

+ 5 - 5
src/interpreter/vm.c

@@ -75,7 +75,7 @@ void VM__ctor(VM* self) {
 
     self->ctx = NULL;
     self->curr_class = NULL;
-    self->curr_function = NULL;
+    self->curr_decl_based_function = NULL;
     memset(&self->trace_info, 0, sizeof(TraceInfo));
 
     FixedMemoryPool__ctor(&self->pool_frame, sizeof(py_Frame), 32);
@@ -492,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);
                 } else {
                     // decl-based binding
-                    self->curr_function = p0;
+                    self->curr_decl_based_function = p0;
                     bool ok = py_callcfunc(fn->cfunc, co->nlocals, argv);
                     self->stack.sp = p0;
-                    self->curr_function = NULL;
+                    self->curr_decl_based_function = NULL;
                     return ok ? RES_RETURN : RES_ERROR;
                 }
             }
@@ -521,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);
                 } else {
                     // decl-based binding
-                    self->curr_function = p0;
+                    self->curr_decl_based_function = p0;
                     bool ok = py_callcfunc(fn->cfunc, co->nlocals, argv);
                     self->stack.sp = p0;
-                    self->curr_function = NULL;
+                    self->curr_decl_based_function = NULL;
                     return ok ? RES_RETURN : RES_ERROR;
                 }
             case FuncType_GENERATOR: {

+ 8 - 0
src/public/modules.c

@@ -797,10 +797,18 @@ static bool function__doc__(int argc, py_Ref argv) {
     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;
+}
+
 py_Type pk_function__register() {
     py_Type type =
         pk_newtype("function", tp_object, NULL, (void (*)(void*))Function__dtor, false, true);
     py_bindproperty(type, "__doc__", function__doc__, NULL);
+    py_bindproperty(type, "__name__", function__name__, NULL);
     return type;
 }
 

+ 1 - 1
src/public/py_exception.c

@@ -154,7 +154,7 @@ void py_clearexc(py_StackRef p0) {
     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_decl_based_function = NULL;
     if(p0) vm->stack.sp = p0;
 }
 

+ 13 - 7
src/public/stack_ops.c

@@ -29,15 +29,15 @@ void py_setdict(py_Ref self, py_Name name, py_Ref val) {
     }
 }
 
-py_ItemRef py_emplacedict(py_Ref self, py_Name name){
+py_ItemRef py_emplacedict(py_Ref self, py_Name name) {
     py_setdict(self, name, py_NIL());
     return py_getdict(self, name);
 }
 
-bool py_applydict(py_Ref self, bool (*f)(py_Name, py_Ref, void *), void *ctx){
+bool py_applydict(py_Ref self, bool (*f)(py_Name, py_Ref, void*), void* ctx) {
     assert(self && self->is_ptr);
     NameDict* dict = PyObject__dict(self->_obj);
-    for(int i = 0; i < dict->length; i++){
+    for(int i = 0; i < dict->length; i++) {
         NameDict_KV* kv = c11__at(NameDict_KV, dict, i);
         bool ok = f(kv->key, &kv->value, ctx);
         if(!ok) return false;
@@ -68,16 +68,22 @@ void py_setslot(py_Ref self, int i, py_Ref val) {
     PyObject__slots(self->_obj)[i] = *val;
 }
 
-py_StackRef py_inspect_currentfunction(){
-    return pk_current_vm->curr_function;
+py_StackRef py_inspect_currentfunction() {
+    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() {
     py_Frame* frame = pk_current_vm->top_frame;
     if(!frame) return NULL;
     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; }
 
 /* Stack References */
@@ -111,7 +117,7 @@ void py_pushnone() {
     py_newnone(vm->stack.sp++);
 }
 
-void py_pushname(py_Name name){
+void py_pushname(py_Name name) {
     VM* vm = pk_current_vm;
     py_newint(vm->stack.sp++, name);
 }