瀏覽代碼

add `__delattr__`

blueloveTH 2 年之前
父節點
當前提交
2cd93de8be
共有 5 個文件被更改,包括 19 次插入1 次删除
  1. 12 0
      3rd/lua_bridge/src/lua_bridge.cpp
  2. 2 0
      docs/bindings_lua.md
  3. 1 1
      docs/features/differences.md
  4. 2 0
      include/pocketpy/vm.h
  5. 2 0
      src/vm.cpp

+ 12 - 0
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<PyLuaTable>(PK_OBJ_GET(Type, args[0]));

+ 2 - 0
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.

+ 1 - 1
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.

+ 2 - 0
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{

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