From 3a3b97c070a66abf72b21647ebe6f4117c313877 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Thu, 12 Oct 2023 00:44:53 +0800 Subject: [PATCH] improve `exec`/`eval` --- src/pocketpy.cpp | 52 +++++++++++++++------------------------- tests/43_eval.py | 11 ++++++++- tests/99_builtin_func.py | 50 -------------------------------------- 3 files changed, 29 insertions(+), 84 deletions(-) diff --git a/src/pocketpy.cpp b/src/pocketpy.cpp index fac6064e..f6832104 100644 --- a/src/pocketpy.cpp +++ b/src/pocketpy.cpp @@ -72,7 +72,6 @@ static dylib_entry_t load_dylib(const char* path){ } #endif - void init_builtins(VM* _vm) { #define BIND_NUM_ARITH_OPT(name, op) \ _vm->bind##name(_vm->tp_int, [](VM* vm, PyObject* lhs, PyObject* rhs) { \ @@ -238,16 +237,29 @@ void init_builtins(VM* _vm) { } }); - _vm->bind_builtin_func<1>("eval", [](VM* vm, ArgsView args) { + _vm->bind(_vm->builtins, "eval(__source, __globals=None)", [](VM* vm, ArgsView args) { CodeObject_ code = vm->compile(CAST(Str&, args[0]), "", EVAL_MODE, true); - FrameId frame = vm->top_frame(); - return vm->_exec(code.get(), frame->_module, frame->_callable, frame->_locals); + PyObject* globals = args[1]; + if(globals == vm->None){ + FrameId frame = vm->top_frame(); + return vm->_exec(code.get(), frame->_module, frame->_callable, frame->_locals); + } + vm->check_non_tagged_type(globals, vm->tp_mappingproxy); + PyObject* obj = PK_OBJ_GET(MappingProxy, globals).obj; + return vm->_exec(code, obj); }); - _vm->bind_builtin_func<1>("exec", [](VM* vm, ArgsView args) { + _vm->bind(_vm->builtins, "exec(__source, __globals=None)", [](VM* vm, ArgsView args) { CodeObject_ code = vm->compile(CAST(Str&, args[0]), "", EXEC_MODE, true); - FrameId frame = vm->top_frame(); - vm->_exec(code.get(), frame->_module, frame->_callable, frame->_locals); + PyObject* globals = args[1]; + if(globals == vm->None){ + FrameId frame = vm->top_frame(); + vm->_exec(code.get(), frame->_module, frame->_callable, frame->_locals); + return vm->None; + } + vm->check_non_tagged_type(globals, vm->tp_mappingproxy); + PyObject* obj = PK_OBJ_GET(MappingProxy, globals).obj; + vm->_exec(code, obj); return vm->None; }); @@ -983,32 +995,6 @@ void init_builtins(VM* _vm) { return VAR(val ? "true" : "false"); }); - const PK_LOCAL_STATIC auto f_bool_add = [](VM* vm, PyObject* lhs, PyObject* rhs) -> PyObject* { - int x = (int)_CAST(bool, lhs); - if(is_int(rhs)) return VAR(x + _CAST(int, rhs)); - if(rhs == vm->True) return VAR(x + 1); - if(rhs == vm->False) return VAR(x); - return vm->NotImplemented; - }; - - const PK_LOCAL_STATIC auto f_bool_mul = [](VM* vm, PyObject* lhs, PyObject* rhs) -> PyObject* { - int x = (int)_CAST(bool, lhs); - if(is_int(rhs)) return VAR(x * _CAST(int, rhs)); - if(rhs == vm->True) return VAR(x); - if(rhs == vm->False) return VAR(0); - return vm->NotImplemented; - }; - - _vm->bind__add__(_vm->tp_bool, f_bool_add); - _vm->bind_method<1>("bool", "__radd__", [](VM* vm, ArgsView args){ - return f_bool_add(vm, args[0], args[1]); - }); - - _vm->bind__mul__(_vm->tp_bool, f_bool_mul); - _vm->bind_method<1>("bool", "__rmul__", [](VM* vm, ArgsView args){ - return f_bool_mul(vm, args[0], args[1]); - }); - _vm->bind__and__(_vm->tp_bool, [](VM* vm, PyObject* lhs, PyObject* rhs) { return VAR(_CAST(bool, lhs) && CAST(bool, rhs)); }); diff --git a/tests/43_eval.py b/tests/43_eval.py index a2fcb06b..c5e91944 100644 --- a/tests/43_eval.py +++ b/tests/43_eval.py @@ -29,4 +29,13 @@ def f(): exec( "exec('b = eval(\"3 + 5\")')" ) - assert b == 8 \ No newline at end of file + assert b == 8 + +class G: pass + +def abc(): + g = G() + exec('a=1', g.__dict__) + return g.a + +assert abc() == 1 \ No newline at end of file diff --git a/tests/99_builtin_func.py b/tests/99_builtin_func.py index 96bf4c3b..345b017e 100644 --- a/tests/99_builtin_func.py +++ b/tests/99_builtin_func.py @@ -557,56 +557,6 @@ assert repr(True) == 'True' assert repr(False) == 'False' - -# 未完全测试准确性----------------------------------------------- -# 58: 851: const PK_LOCAL_STATIC auto f_bool_add = [](VM* vm, PyObject* lhs, PyObject* rhs) -> PyObject* { -# #####: 852: int x = (int)_CAST(bool, lhs); -# #####: 853: if(is_int(rhs)) return VAR(x + _CAST(int, rhs)); -# #####: 854: if(rhs == vm->True) return VAR(x + 1); -# #####: 855: if(rhs == vm->False) return VAR(x); -# #####: 856: return vm->NotImplemented; -# #####: 857: }; -# -# 58: 867: _vm->bind__add__(_vm->tp_bool, f_bool_add); -# test bool.__add__: -assert type(True + 1) is int -assert type(True + False) is int -assert type(True + True) is int - - - -# 未完全测试准确性----------------------------------------------- -# 58: 859: const PK_LOCAL_STATIC auto f_bool_mul = [](VM* vm, PyObject* lhs, PyObject* rhs) -> PyObject* { -# #####: 860: int x = (int)_CAST(bool, lhs); -# #####: 861: if(is_int(rhs)) return VAR(x * _CAST(int, rhs)); -# #####: 862: if(rhs == vm->True) return VAR(x); -# #####: 863: if(rhs == vm->False) return VAR(0); -# #####: 864: return vm->NotImplemented; -# #####: 865: }; -# -# 58: 872: _vm->bind__mul__(_vm->tp_bool, f_bool_mul); -# test bool.__mul__: -assert type(True * 1) is int -assert type(True * False) is int -assert type(True * True) is int - - -# 未完全测试准确性----------------------------------------------- -# 116: 873: _vm->bind_method<1>("bool", "__radd__", [](VM* vm, ArgsView args){ -# #####: 874: return f_bool_add(vm, args[0], args[1]); -# -: 875: }); -# test bool.__radd__: -assert type(1 + True) is int - - -# 未完全测试准确性----------------------------------------------- -# 116: 878: _vm->bind_method<1>("bool", "__rmul__", [](VM* vm, ArgsView args){ -# #####: 879: return f_bool_mul(vm, args[0], args[1]); -# -: 880: }); -# test bool.__rmul__: -assert type(1 * True) is int - - # 未完全测试准确性----------------------------------------------- # 116: 882: _vm->bind__and__(_vm->tp_bool, [](VM* vm, PyObject* lhs, PyObject* rhs) { # #####: 883: return VAR(_CAST(bool, lhs) && CAST(bool, rhs));