This commit is contained in:
blueloveTH 2024-01-16 16:14:13 +08:00
parent 683e175289
commit e7f947c987
3 changed files with 22 additions and 21 deletions

View File

@ -20,14 +20,12 @@ The easiest way to test a feature is to [try it on your browser](https://pocketp
## Unimplemented features ## Unimplemented features
1. `__getattr__` and `__setattr__`. 1. Descriptor protocol `__get__` and `__set__`. However, `@property` is implemented.
2. Descriptor protocol `__get__` and `__set__`. However, `@property` is implemented. 2. `__slots__` in class definition.
3. `__slots__` in class definition. 3. `else` clause in try..except.
4. Access the exception object in try..except. 4. Inplace methods like `__iadd__` and `__imul__`.
5. `else` clause in try..except. 5. `__del__` in class definition.
6. Inplace methods like `__iadd__` and `__imul__`. 6. Multiple inheritance.
7. `__del__` in class definition.
8. Multiple inheritance.
## Different behaviors ## Different behaviors
@ -42,3 +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. 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. 10. `%`, `&`, `//`, `^` and `|` for `int` behave the same as C, not python.
11. `str.split` and `str.splitlines` will remove all empty entries. 11. `str.split` and `str.splitlines` will remove all empty entries.
12. `__getattr__` and `__setattr__` can only be set in cpp.

View File

@ -1604,6 +1604,16 @@ void VM::post_init(){
return vm->None; return vm->None;
}); });
_all_types[tp_module].m__getattr__ = [](VM* vm, PyObject* obj, StrName name) -> PyObject*{
const Str& path = CAST(Str&, obj->attr(__path__));
PyObject* mod = vm->py_import(fmt(path, ".", name.sv()), false);
if(mod != nullptr){
obj->attr().set(name, mod);
return mod;
}
return nullptr;
};
bind_method<1>(tp_property, "setter", [](VM* vm, ArgsView args) { bind_method<1>(tp_property, "setter", [](VM* vm, ArgsView args) {
Property& self = _CAST(Property&, args[0]); Property& self = _CAST(Property&, args[0]);
// The setter's name is not necessary to be the same as the property's name // The setter's name is not necessary to be the same as the property's name

View File

@ -1041,17 +1041,8 @@ PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){
const PyTypeInfo* ti = &_all_types[objtype]; const PyTypeInfo* ti = &_all_types[objtype];
if(ti->m__getattr__){ if(ti->m__getattr__){
return ti->m__getattr__(this, obj, name); PyObject* ret = ti->m__getattr__(this, obj, name);
} if(ret) return ret;
if(is_non_tagged_type(obj, tp_module)){
Str path = CAST(Str&, obj->attr(__path__));
path = path + "." + name.sv();
PyObject* mod = py_import(path, false);
if(mod != nullptr){
obj->attr().set(name, mod);
return mod;
}
} }
if(throw_err) AttributeError(obj, name); if(throw_err) AttributeError(obj, name);
@ -1120,8 +1111,9 @@ PyObject* VM::get_unbound_method(PyObject* obj, StrName name, PyObject** self, b
} }
const PyTypeInfo* ti = &_all_types[objtype]; const PyTypeInfo* ti = &_all_types[objtype];
if(fallback && ti->m__getattr__){ if(ti->m__getattr__){
return ti->m__getattr__(this, obj, name); PyObject* ret = ti->m__getattr__(this, obj, name);
if(ret) return ret;
} }
if(throw_err) AttributeError(obj, name); if(throw_err) AttributeError(obj, name);