diff --git a/include/pocketpy/interpreter/vm.h b/include/pocketpy/interpreter/vm.h index 9a407c23..b90a6b7a 100644 --- a/include/pocketpy/interpreter/vm.h +++ b/include/pocketpy/interpreter/vm.h @@ -46,7 +46,6 @@ typedef struct VM { py_TValue reg[8]; // users' registers py_TValue* __curr_class; - FuncDecl_ __dynamic_func_decl; py_TValue __vectorcall_buffer[PK_MAX_CO_VARNAMES]; ManagedHeap heap; diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index ac1996e0..099910af 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -75,6 +75,15 @@ bool py_exec(const char* source, enum py_CompileMode mode, py_Ref module) PY_RAISE; +/// Run a source string in dynamic mode. +/// Assume `globals()` and `locals()` are pushed to the stack. +/// After the execution, the result will be set to `py_retval()`. +/// The stack size will be reduced by 2. +bool py_execdynamic(const char* source, + const char* filename, + enum py_CompileMode mode, + py_Ref module) PY_RAISE; + /************* Values Creation *************/ /// Create an `int` object. diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 775d773b..4b51d69f 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -290,14 +290,8 @@ FrameResult VM__run_top_frame(VM* self) { if(slot != NULL) { *slot = *TOP(); // store in locals if possible } else { - // Function& func = frame->_callable->as(); - // if(func.decl == __dynamic_func_decl) { - // assert(func._closure != nullptr); - // func._closure->set(_name, _0); - // } else { - // NameError(_name); - // goto __ERROR; - // } + NameError(name); + goto __ERROR; } } else { py_setdict(frame->module, name, TOP()); @@ -351,14 +345,8 @@ FrameResult VM__run_top_frame(VM* self) { if(slot) { py_newnil(slot); } else { - // Function& func = frame->_callable->as(); - // if(func.decl == __dynamic_func_decl) { - // assert(func._closure != nullptr); - // bool ok = func._closure->del(_name); - // if(!ok) vm->NameError(_name); - // } else { - // vm->NameError(_name); - // } + NameError(name); + goto __ERROR; } } else { bool ok = py_deldict(frame->module, name); diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 8df205f1..92194873 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -71,7 +71,6 @@ void VM__ctor(VM* self) { self->is_stopiteration = false; self->__curr_class = NULL; - self->__dynamic_func_decl = NULL; ManagedHeap__ctor(&self->heap, self); ValueStack__ctor(&self->stack); @@ -212,7 +211,6 @@ void VM__ctor(VM* self) { } void VM__dtor(VM* self) { - if(self->__dynamic_func_decl) { PK_DECREF(self->__dynamic_func_decl); } // destroy all objects ManagedHeap__dtor(&self->heap); // clear frames diff --git a/src/public/internal.c b/src/public/internal.c index 38eff61a..6131c9f5 100644 --- a/src/public/internal.c +++ b/src/public/internal.c @@ -77,10 +77,14 @@ const char* pk_opname(Opcode op) { return OP_NAMES[op]; } -bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) { +static bool _py_exec(const char* source, + const char* filename, + enum py_CompileMode mode, + py_Ref module, + bool is_dynamic) { VM* vm = pk_current_vm; CodeObject co; - SourceData_ src = SourceData__rcnew(source, filename, mode, false); + SourceData_ src = SourceData__rcnew(source, filename, mode, is_dynamic); Error* err = pk_compile(src, &co); if(err) { py_exception(tp_SyntaxError, err->msg); @@ -93,7 +97,13 @@ bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, if(!module) module = &vm->main; - Frame* frame = Frame__new(&co, module, false, vm->stack.sp, vm->stack.sp); + py_StackRef sp = vm->stack.sp; + if(is_dynamic) { + // [globals, locals] + sp -= 2; + } + + Frame* frame = Frame__new(&co, module, false, sp, sp); VM__push_frame(vm, frame); FrameResult res = VM__run_top_frame(vm); CodeObject__dtor(&co); @@ -103,6 +113,17 @@ bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, c11__unreachedable(); } +bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) { + return _py_exec(source, filename, mode, module, false); +} + +bool py_execdynamic(const char* source, + const char* filename, + enum py_CompileMode mode, + py_Ref module) { + return _py_exec(source, filename, mode, module, true); +} + bool py_call(py_Ref f, int argc, py_Ref argv) { if(f->type == tp_nativefunc) { return py_callcfunc(f->_cfunc, argc, argv); @@ -120,8 +141,11 @@ bool py_callcfunc(py_CFunction f, int argc, py_Ref argv) { py_newnil(py_retval()); bool ok = f(argc, argv); if(!ok) return false; - if(py_peek(0) != p0) c11__abort("py_CFunction corrupts the stack! Did you forget to call `py_pop()`?"); - if(py_isnil(py_retval())) c11__abort("py_CFunction returns nothing! Did you forget to call `py_newnone(py_retval())`?"); + if(py_peek(0) != p0) + c11__abort("py_CFunction corrupts the stack! Did you forget to call `py_pop()`?"); + if(py_isnil(py_retval())) + c11__abort( + "py_CFunction returns nothing! Did you forget to call `py_newnone(py_retval())`?"); return true; }