Kaynağa Gözat

improve `exec`/`eval`

blueloveTH 2 yıl önce
ebeveyn
işleme
3a3b97c070
3 değiştirilmiş dosya ile 29 ekleme ve 84 silme
  1. 19 33
      src/pocketpy.cpp
  2. 10 1
      tests/43_eval.py
  3. 0 50
      tests/99_builtin_func.py

+ 19 - 33
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>", 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>", 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));
     });

+ 10 - 1
tests/43_eval.py

@@ -29,4 +29,13 @@ def f():
     exec(
         "exec('b = eval(\"3 + 5\")')"
     )
-    assert b == 8
+    assert b == 8
+
+class G: pass
+
+def abc():
+    g = G()
+    exec('a=1', g.__dict__)
+    return g.a
+
+assert abc() == 1

+ 0 - 50
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));