diff --git a/include/pocketpy/vm.h b/include/pocketpy/vm.h index 7200a176..0478872a 100644 --- a/include/pocketpy/vm.h +++ b/include/pocketpy/vm.h @@ -449,6 +449,7 @@ public: Str disassemble(CodeObject_ co); void init_builtin_types(); PyObject* getattr(PyObject* obj, StrName name, bool throw_err=true); + void delattr(PyObject* obj, StrName name); PyObject* get_unbound_method(PyObject* obj, StrName name, PyObject** self, bool throw_err=true, bool fallback=false); void parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step); PyObject* format(Str, PyObject*); diff --git a/src/ceval.cpp b/src/ceval.cpp index d0a71366..4cae24eb 100644 --- a/src/ceval.cpp +++ b/src/ceval.cpp @@ -220,8 +220,7 @@ __NEXT_STEP:; TARGET(DELETE_ATTR) _0 = POPX(); _name = StrName(byte.arg); - if(is_tagged(_0) || !_0->is_attr_valid()) TypeError("cannot delete attribute"); - if(!_0->attr().del(_name)) AttributeError(_0, _name); + delattr(_0, _name); DISPATCH(); TARGET(DELETE_SUBSCR) _1 = POPX(); diff --git a/src/pocketpy.cpp b/src/pocketpy.cpp index 10ccfa1e..c49cbb2b 100644 --- a/src/pocketpy.cpp +++ b/src/pocketpy.cpp @@ -309,6 +309,11 @@ void init_builtins(VM* _vm) { return vm->getattr(args[0], name); }); + _vm->bind_builtin_func<2>("delattr", [](VM* vm, ArgsView args) { + vm->delattr(args[0], CAST(Str&, args[1])); + return vm->None; + }); + _vm->bind_builtin_func<1>("hex", [](VM* vm, ArgsView args) { std::stringstream ss; ss << std::hex << CAST(i64, args[0]); diff --git a/src/vm.cpp b/src/vm.cpp index f84c3101..42e26d6f 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -915,6 +915,11 @@ PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){ return nullptr; } +void VM::delattr(PyObject *_0, StrName _name){ + if(is_tagged(_0) || !_0->is_attr_valid()) TypeError("cannot delete attribute"); + if(!_0->attr().del(_name)) AttributeError(_0, _name); +} + // https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){ PyObject* objtype; diff --git a/tests/07_dict.py b/tests/07_dict.py index 2721c1a9..08f649b3 100644 --- a/tests/07_dict.py +++ b/tests/07_dict.py @@ -113,6 +113,7 @@ for i in range(2, 1000): a = {'0': 0, '1': 1} b = ['0', '1'] +# dict delete test data = [] j = 6 for i in range(65535): @@ -127,6 +128,19 @@ for i in range(len(data)): y = b.pop() del a[y] +# namedict delete test +class A: pass +a = A() +b = ['0', '1'] + +for i in range(len(data)): + z = data[i] + setattr(a, str(z), i) + b.append(z) + if i % 3 == 0: + y = b.pop() + delattr(a, y) + a = {1: 2, 3: 4} assert a.pop(1) == 2 try: diff --git a/tests/80_linalg.py b/tests/80_linalg.py index 2f129985..d5d1ed87 100644 --- a/tests/80_linalg.py +++ b/tests/80_linalg.py @@ -60,12 +60,12 @@ assert str(static_test_vec3_float) == 'vec3(3.1887, -1.0984e+06, 9)' assert str(static_test_vec3_int) == 'vec3(278, -1.39197e+13, 1.36422e+15)' # test __getnewargs__ -element_name_list = [e for e in dir(test_vec3) if e in 'x,y,z,w'] +element_name_list = ['x', 'y', 'z'] element_value_list = [getattr(test_vec3, attr) for attr in element_name_list] assert tuple(element_value_list) == test_vec3.__getnewargs__() # test copy -element_name_list = [e for e in dir(test_vec3) if e in 'x,y,z,w'] +element_name_list = ['x', 'y', 'z'] element_value_list = [getattr(test_vec3, attr) for attr in element_name_list] copy_element_value_list = [getattr(test_vec3.copy(), attr) for attr in element_name_list] assert element_value_list == copy_element_value_list