mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
add py_exec
and py_eval
prototype
This commit is contained in:
parent
44aed24d3b
commit
331dedcd28
@ -90,7 +90,34 @@ struct function<Ret(Params...)>{
|
||||
template<typename F>
|
||||
function(F&& f) : _impl(std::forward<F>(f)){
|
||||
_wrapper = [](const any& impl, Params... params) -> Ret{
|
||||
return impl.cast<std::decay_t<F>>()(std::forward<Params>(params)...);
|
||||
return impl._cast<std::decay_t<F>>()(std::forward<Params>(params)...);
|
||||
};
|
||||
}
|
||||
|
||||
Ret operator()(Params... params) const{
|
||||
if(!_wrapper) throw std::runtime_error("empty function");
|
||||
return _wrapper(_impl, std::forward<Params>(params)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct lightfunction;
|
||||
|
||||
template<typename Ret, typename... Params>
|
||||
struct lightfunction<Ret(Params...)>{
|
||||
void* _impl;
|
||||
Ret (*_wrapper)(void*, Params...);
|
||||
|
||||
lightfunction() : _impl(nullptr), _wrapper(nullptr) {}
|
||||
|
||||
operator bool() const { return _wrapper != nullptr; }
|
||||
|
||||
template<typename F>
|
||||
lightfunction(const F& f){
|
||||
_impl = (F*)(&f);
|
||||
_wrapper = [](void* impl, Params... params) -> Ret{
|
||||
F* f = (F*)(impl);
|
||||
return (*f)(std::forward<Params>(params)...);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -207,6 +207,9 @@ public:
|
||||
bool py_ne(PyObject* lhs, PyObject* rhs) { // (lhs, rhs) -> lhs != rhs
|
||||
return !py_eq(lhs, rhs);
|
||||
}
|
||||
|
||||
void py_exec(std::string_view, PyObject*, PyObject*); // exec(source, globals, locals)
|
||||
PyObject* py_eval(std::string_view, PyObject*, PyObject*); // eval(source, globals, locals)
|
||||
#endif
|
||||
|
||||
#if PK_REGION("Utility Methods")
|
||||
@ -408,7 +411,7 @@ public:
|
||||
#endif
|
||||
void __breakpoint();
|
||||
PyObject* __format_object(PyObject*, Str);
|
||||
PyObject* __run_top_frame();
|
||||
PyObject* __run_top_frame(lightfunction<void(Frame*)> on_will_pop_base_frame = {});
|
||||
void __pop_frame();
|
||||
PyObject* __py_generator(Frame&& frame, ArgsView buffer);
|
||||
void __op_unpack_sequence(uint16_t arg);
|
||||
|
@ -80,7 +80,7 @@ bool VM::py_ge(PyObject* _0, PyObject* _1){
|
||||
|
||||
#undef BINARY_F_COMPARE
|
||||
|
||||
PyObject* VM::__run_top_frame(){
|
||||
PyObject* VM::__run_top_frame(lightfunction<void(Frame*)> on_will_pop_base_frame){
|
||||
Frame* frame = &callstack.top();
|
||||
const Frame* base_frame = frame;
|
||||
bool need_raise = false;
|
||||
@ -709,10 +709,12 @@ __NEXT_STEP:;
|
||||
} DISPATCH()
|
||||
case OP_RETURN_VALUE:{
|
||||
PyObject* _0 = byte.arg == BC_NOARG ? POPX() : None;
|
||||
__pop_frame();
|
||||
if(frame == base_frame){ // [ frameBase<- ]
|
||||
if(on_will_pop_base_frame) on_will_pop_base_frame(frame);
|
||||
__pop_frame();
|
||||
return _0;
|
||||
}else{
|
||||
__pop_frame();
|
||||
frame = &callstack.top();
|
||||
PUSH(_0);
|
||||
goto __NEXT_FRAME;
|
||||
@ -982,6 +984,9 @@ __NEXT_STEP:;
|
||||
PyObject* e_obj = POPX();
|
||||
Exception& _e = PK_OBJ_GET(Exception, e_obj);
|
||||
bool is_base_frame_to_be_popped = frame == base_frame;
|
||||
if(is_base_frame_to_be_popped){
|
||||
if(on_will_pop_base_frame) on_will_pop_base_frame(frame);
|
||||
}
|
||||
__pop_frame();
|
||||
if(callstack.empty()) throw _e; // propagate to the top level
|
||||
frame = &callstack.top();
|
||||
|
@ -197,29 +197,13 @@ void __init_builtins(VM* _vm) {
|
||||
}
|
||||
});
|
||||
|
||||
_vm->bind(_vm->builtins, "eval(__source, __globals=None)", [](VM* vm, ArgsView args) {
|
||||
CodeObject_ code = vm->compile(CAST(Str&, args[0]), "<eval>", EVAL_MODE, true);
|
||||
PyObject* globals = args[1];
|
||||
if(globals == vm->None){
|
||||
Frame* frame = &vm->callstack.top();
|
||||
return vm->_exec(code.get(), frame->_module, frame->_callable, frame->_locals);
|
||||
}
|
||||
vm->check_type(globals, VM::tp_mappingproxy);
|
||||
PyObject* obj = PK_OBJ_GET(MappingProxy, globals).obj;
|
||||
return vm->_exec(code, obj);
|
||||
// we use `_0`, `_1` and `_2` here to disable keyword arguments (but with default values)
|
||||
_vm->bind(_vm->builtins, "eval(_0, _1=None, _2=None)", [](VM* vm, ArgsView args) {
|
||||
return vm->py_eval(CAST(Str&, args[0]), args[1], args[2]);
|
||||
});
|
||||
|
||||
_vm->bind(_vm->builtins, "exec(__source, __globals=None)", [](VM* vm, ArgsView args) {
|
||||
CodeObject_ code = vm->compile(CAST(Str&, args[0]), "<exec>", EXEC_MODE, true);
|
||||
PyObject* globals = args[1];
|
||||
if(globals == vm->None){
|
||||
Frame* frame = &vm->callstack.top();
|
||||
vm->_exec(code.get(), frame->_module, frame->_callable, frame->_locals);
|
||||
return vm->None;
|
||||
}
|
||||
vm->check_type(globals, VM::tp_mappingproxy);
|
||||
PyObject* obj = PK_OBJ_GET(MappingProxy, globals).obj;
|
||||
vm->_exec(code, obj);
|
||||
_vm->bind(_vm->builtins, "exec(_0, _1=None, _2=None)", [](VM* vm, ArgsView args) {
|
||||
vm->py_exec(CAST(Str&, args[0]), args[1], args[2]);
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
|
25
src/vm.cpp
25
src/vm.cpp
@ -505,6 +505,31 @@ i64 VM::py_hash(PyObject* obj){
|
||||
}
|
||||
}
|
||||
|
||||
void VM::py_exec(std::string_view source, PyObject* globals, PyObject* locals){
|
||||
(void)(locals);
|
||||
CodeObject_ code = vm->compile(source, "<exec>", EXEC_MODE, true);
|
||||
if(globals == vm->None){
|
||||
Frame* frame = &vm->callstack.top();
|
||||
vm->_exec(code.get(), frame->_module, frame->_callable, frame->_locals);
|
||||
return;
|
||||
}
|
||||
vm->check_type(globals, VM::tp_mappingproxy);
|
||||
PyObject* obj = PK_OBJ_GET(MappingProxy, globals).obj;
|
||||
vm->_exec(code, obj);
|
||||
}
|
||||
|
||||
PyObject* VM::py_eval(std::string_view source, PyObject* globals, PyObject* locals){
|
||||
(void)(locals);
|
||||
CodeObject_ code = vm->compile(source, "<eval>", EVAL_MODE, true);
|
||||
if(globals == vm->None){
|
||||
Frame* frame = &vm->callstack.top();
|
||||
return vm->_exec(code.get(), frame->_module, frame->_callable, frame->_locals);
|
||||
}
|
||||
vm->check_type(globals, VM::tp_mappingproxy);
|
||||
PyObject* obj = PK_OBJ_GET(MappingProxy, globals).obj;
|
||||
return vm->_exec(code, obj);
|
||||
}
|
||||
|
||||
PyObject* VM::__format_object(PyObject* obj, Str spec){
|
||||
if(spec.empty()) return VAR(py_str(obj));
|
||||
char type;
|
||||
|
Loading…
x
Reference in New Issue
Block a user