refactor globals and locals

This commit is contained in:
liuyang18 2025-03-24 11:11:03 +08:00
parent 66a7591efd
commit 2336d22666
3 changed files with 35 additions and 23 deletions

View File

@ -110,6 +110,10 @@ 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);
/// Python equivalent to `globals()` with respect to the given frame.
PK_API void py_Frame_newglobals(py_Frame* frame, py_OutRef out);
/// Python equivalent to `locals()` with respect to the given frame.
PK_API void py_Frame_newlocals(py_Frame* frame, py_OutRef out);
/// Get the function object of the frame.
/// Returns `NULL` if not available.
PK_API py_StackRef py_Frame_function(py_Frame* frame);

View File

@ -192,6 +192,35 @@ const char* py_Frame_sourceloc(py_Frame* self, int* lineno) {
return loc.src->filename->data;
}
void py_Frame_newglobals(py_Frame* frame, py_Ref out) {
if(!frame) {
pk_mappingproxy__namedict(out, &pk_current_vm->main);
return;
}
if(frame->globals->type == tp_module) {
pk_mappingproxy__namedict(out, frame->globals);
} else {
*out = *frame->globals; // dict
}
}
void py_Frame_newlocals(py_Frame* frame, py_Ref out) {
if(!frame) {
py_newdict(out);
return;
}
if(frame->is_locals_special) {
switch(frame->locals->type) {
case tp_locals: frame = frame->locals->_ptr; break;
case tp_dict: *out = *frame->locals; return;
case tp_nil: py_newdict(out); return;
default: c11__unreachable();
}
}
FastLocals__to_dict(frame->locals, frame->co);
py_assign(out, py_retval());
}
py_StackRef py_Frame_function(py_Frame* self) {
if(self->is_locals_special) return NULL;
assert(self->p0->type == tp_function);

View File

@ -501,33 +501,12 @@ static bool builtins_locals(int argc, py_Ref argv) {
void py_newglobals(py_Ref out) {
py_Frame* frame = pk_current_vm->top_frame;
if(!frame) {
pk_mappingproxy__namedict(out, &pk_current_vm->main);
return;
}
if(frame->globals->type == tp_module) {
pk_mappingproxy__namedict(out, frame->globals);
} else {
*out = *frame->globals; // dict
}
py_Frame_newglobals(frame, out);
}
void py_newlocals(py_Ref out) {
py_Frame* frame = pk_current_vm->top_frame;
if(!frame) {
py_newdict(out);
return;
}
if(frame->is_locals_special) {
switch(frame->locals->type) {
case tp_locals: frame = frame->locals->_ptr; break;
case tp_dict: *out = *frame->locals; return;
case tp_nil: py_newdict(out); return;
default: c11__unreachable();
}
}
FastLocals__to_dict(frame->locals, frame->co);
py_assign(out, py_retval());
py_Frame_newlocals(frame, out);
}
static void pk_push_special_locals() {