diff --git a/3rd/lua_bridge/src/lua_bridge.cpp b/3rd/lua_bridge/src/lua_bridge.cpp index c7c496c0..e374b7e0 100644 --- a/3rd/lua_bridge/src/lua_bridge.cpp +++ b/3rd/lua_bridge/src/lua_bridge.cpp @@ -67,6 +67,18 @@ struct PyLuaTable: PyLuaObject{ ) }; + ti->m__delattr__ = [](VM* vm, PyObject* obj, StrName name){ + const PyLuaTable& self = _CAST(PyLuaTable&, obj); + LUA_PROTECTED( + lua_rawgeti(_L, LUA_REGISTRYINDEX, self.r); + lua_pushstring(_L, std::string(name.sv()).c_str()); + lua_pushnil(_L); + lua_settable(_L, -3); + lua_pop(_L, 1); + ) + return true; + }; + vm->bind_constructor<1>(type, [](VM* vm, ArgsView args){ lua_newtable(_L); // push an empty table onto the stack PyObject* obj = vm->heap.gcnew(PK_OBJ_GET(Type, args[0])); diff --git a/docs/bindings_lua.md b/docs/bindings_lua.md index 3e0d7e24..930e950b 100644 --- a/docs/bindings_lua.md +++ b/docs/bindings_lua.md @@ -48,8 +48,10 @@ class Table: def __getitem__(self, key): ... def __setitem__(self, key, value): ... + def __delitem__(self, key): ... def __getattr__(self, key): ... def __setattr__(self, key, value): ... + def __delattr__(self, key): ... ``` Only basic types can be passed between python and lua. diff --git a/docs/features/differences.md b/docs/features/differences.md index b0aba9ab..d8045c9b 100644 --- a/docs/features/differences.md +++ b/docs/features/differences.md @@ -40,4 +40,4 @@ The easiest way to test a feature is to [try it on your browser](https://pocketp 9. A `Tab` is equivalent to 4 spaces. You can mix `Tab` and spaces in indentation, but it is not recommended. 10. `%`, `&`, `//`, `^` and `|` for `int` behave the same as C, not python. 11. `str.split` and `str.splitlines` will remove all empty entries. -12. `__getattr__` and `__setattr__` can only be set in cpp. +12. `__getattr__`, `__setattr__` and `__delattr__` can only be set in cpp. diff --git a/include/pocketpy/vm.h b/include/pocketpy/vm.h index acfe3a80..8bc71e51 100644 --- a/include/pocketpy/vm.h +++ b/include/pocketpy/vm.h @@ -100,6 +100,8 @@ struct PyTypeInfo{ // attributes void (*m__setattr__)(VM* vm, PyObject*, StrName, PyObject*) = nullptr; PyObject* (*m__getattr__)(VM* vm, PyObject*, StrName) = nullptr; + bool (*m__delattr__)(VM* vm, PyObject*, StrName) = nullptr; + }; struct FrameId{ diff --git a/src/vm.cpp b/src/vm.cpp index 31a4b22b..bdc99a78 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -983,6 +983,8 @@ __FAST_CALL: } void VM::delattr(PyObject *_0, StrName _name){ + const PyTypeInfo* ti = _inst_type_info(_0); + if(ti->m__delattr__ && ti->m__delattr__(this, _0, _name)) return; if(is_tagged(_0) || !_0->is_attr_valid()) TypeError("cannot delete attribute"); if(!_0->attr().del(_name)) AttributeError(_0, _name); }