mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40: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>
|
template<typename F>
|
||||||
function(F&& f) : _impl(std::forward<F>(f)){
|
function(F&& f) : _impl(std::forward<F>(f)){
|
||||||
_wrapper = [](const any& impl, Params... params) -> Ret{
|
_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
|
bool py_ne(PyObject* lhs, PyObject* rhs) { // (lhs, rhs) -> lhs != rhs
|
||||||
return !py_eq(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
|
#endif
|
||||||
|
|
||||||
#if PK_REGION("Utility Methods")
|
#if PK_REGION("Utility Methods")
|
||||||
@ -408,7 +411,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
void __breakpoint();
|
void __breakpoint();
|
||||||
PyObject* __format_object(PyObject*, Str);
|
PyObject* __format_object(PyObject*, Str);
|
||||||
PyObject* __run_top_frame();
|
PyObject* __run_top_frame(lightfunction<void(Frame*)> on_will_pop_base_frame = {});
|
||||||
void __pop_frame();
|
void __pop_frame();
|
||||||
PyObject* __py_generator(Frame&& frame, ArgsView buffer);
|
PyObject* __py_generator(Frame&& frame, ArgsView buffer);
|
||||||
void __op_unpack_sequence(uint16_t arg);
|
void __op_unpack_sequence(uint16_t arg);
|
||||||
|
@ -80,7 +80,7 @@ bool VM::py_ge(PyObject* _0, PyObject* _1){
|
|||||||
|
|
||||||
#undef BINARY_F_COMPARE
|
#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();
|
Frame* frame = &callstack.top();
|
||||||
const Frame* base_frame = frame;
|
const Frame* base_frame = frame;
|
||||||
bool need_raise = false;
|
bool need_raise = false;
|
||||||
@ -709,10 +709,12 @@ __NEXT_STEP:;
|
|||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_RETURN_VALUE:{
|
case OP_RETURN_VALUE:{
|
||||||
PyObject* _0 = byte.arg == BC_NOARG ? POPX() : None;
|
PyObject* _0 = byte.arg == BC_NOARG ? POPX() : None;
|
||||||
__pop_frame();
|
|
||||||
if(frame == base_frame){ // [ frameBase<- ]
|
if(frame == base_frame){ // [ frameBase<- ]
|
||||||
|
if(on_will_pop_base_frame) on_will_pop_base_frame(frame);
|
||||||
|
__pop_frame();
|
||||||
return _0;
|
return _0;
|
||||||
}else{
|
}else{
|
||||||
|
__pop_frame();
|
||||||
frame = &callstack.top();
|
frame = &callstack.top();
|
||||||
PUSH(_0);
|
PUSH(_0);
|
||||||
goto __NEXT_FRAME;
|
goto __NEXT_FRAME;
|
||||||
@ -982,6 +984,9 @@ __NEXT_STEP:;
|
|||||||
PyObject* e_obj = POPX();
|
PyObject* e_obj = POPX();
|
||||||
Exception& _e = PK_OBJ_GET(Exception, e_obj);
|
Exception& _e = PK_OBJ_GET(Exception, e_obj);
|
||||||
bool is_base_frame_to_be_popped = frame == base_frame;
|
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();
|
__pop_frame();
|
||||||
if(callstack.empty()) throw _e; // propagate to the top level
|
if(callstack.empty()) throw _e; // propagate to the top level
|
||||||
frame = &callstack.top();
|
frame = &callstack.top();
|
||||||
|
@ -197,29 +197,13 @@ void __init_builtins(VM* _vm) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind(_vm->builtins, "eval(__source, __globals=None)", [](VM* vm, ArgsView args) {
|
// we use `_0`, `_1` and `_2` here to disable keyword arguments (but with default values)
|
||||||
CodeObject_ code = vm->compile(CAST(Str&, args[0]), "<eval>", EVAL_MODE, true);
|
_vm->bind(_vm->builtins, "eval(_0, _1=None, _2=None)", [](VM* vm, ArgsView args) {
|
||||||
PyObject* globals = args[1];
|
return vm->py_eval(CAST(Str&, args[0]), args[1], args[2]);
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind(_vm->builtins, "exec(__source, __globals=None)", [](VM* vm, ArgsView args) {
|
_vm->bind(_vm->builtins, "exec(_0, _1=None, _2=None)", [](VM* vm, ArgsView args) {
|
||||||
CodeObject_ code = vm->compile(CAST(Str&, args[0]), "<exec>", EXEC_MODE, true);
|
vm->py_exec(CAST(Str&, args[0]), args[1], args[2]);
|
||||||
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);
|
|
||||||
return vm->None;
|
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){
|
PyObject* VM::__format_object(PyObject* obj, Str spec){
|
||||||
if(spec.empty()) return VAR(py_str(obj));
|
if(spec.empty()) return VAR(py_str(obj));
|
||||||
char type;
|
char type;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user