diff --git a/include/pocketpy/interpreter/vm.h b/include/pocketpy/interpreter/vm.h index 1aca1336..f40c1174 100644 --- a/include/pocketpy/interpreter/vm.h +++ b/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]; diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 45fbb0d7..5315dc0c 100644 --- a/include/pocketpy/pocketpy.h +++ b/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. diff --git a/src/interpreter/frame.c b/src/interpreter/frame.c index ae9cc2f0..e8e3293b 100644 --- a/src/interpreter/frame.c +++ b/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; } \ No newline at end of file diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 4905e4db..e0900bc9 100644 --- a/src/interpreter/vm.c +++ b/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: { diff --git a/src/public/modules.c b/src/public/modules.c index 3f77d7db..c07e9be6 100644 --- a/src/public/modules.c +++ b/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; } diff --git a/src/public/py_exception.c b/src/public/py_exception.c index e716b655..1b2e3aeb 100644 --- a/src/public/py_exception.c +++ b/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; } diff --git a/src/public/stack_ops.c b/src/public/stack_ops.c index ccf5972a..055cf46d 100644 --- a/src/public/stack_ops.c +++ b/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); }