mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-23 04:50:17 +00:00
add super()
This commit is contained in:
parent
d9cf73a6d3
commit
5412186365
@ -73,7 +73,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<Function> _Func;
|
typedef std::shared_ptr<Function> _Func;
|
||||||
typedef std::variant<_Int,_Float,bool,_Str,PyVarList,_CppFunc,_Func,std::shared_ptr<_Iterator>,_BoundedMethod,_Range,_Slice,_Pointer> _Value;
|
typedef std::variant<PyVar,_Int,_Float,bool,_Str,PyVarList,_CppFunc,_Func,std::shared_ptr<_Iterator>,_BoundedMethod,_Range,_Slice,_Pointer> _Value;
|
||||||
|
|
||||||
const int _SIZEOF_VALUE = sizeof(_Value);
|
const int _SIZEOF_VALUE = sizeof(_Value);
|
||||||
|
|
||||||
|
@ -56,6 +56,13 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
return vm->PyStr(tvm->readStdin());
|
return vm->PyStr(tvm->readStdin());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_vm->bindBuiltinFunc("super", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
|
vm->__checkArgSize(args, 0);
|
||||||
|
auto it = vm->topFrame()->f_locals.find("self"_c);
|
||||||
|
if(it == vm->topFrame()->f_locals.end()) vm->typeError("super() can only be called in a class method");
|
||||||
|
return vm->newObject(vm->_tp_super, it->second);
|
||||||
|
});
|
||||||
|
|
||||||
_vm->bindBuiltinFunc("eval", [](VM* vm, const pkpy::ArgList& args) {
|
_vm->bindBuiltinFunc("eval", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
vm->__checkArgSize(args, 1);
|
vm->__checkArgSize(args, 1);
|
||||||
const _Str& expr = vm->PyStr_AS_C(args[0]);
|
const _Str& expr = vm->PyStr_AS_C(args[0]);
|
||||||
|
47
src/vm.h
47
src/vm.h
@ -588,16 +588,34 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyVarOrNull getAttr(const PyVar& obj, const _Str& name, bool throw_err=true) {
|
PyVarOrNull getAttr(const PyVar& obj, const _Str& name, bool throw_err=true) {
|
||||||
auto it = obj->attribs.find(name);
|
PyVarDict::iterator it;
|
||||||
if(it != obj->attribs.end()) return it->second;
|
PyObject* cls;
|
||||||
|
|
||||||
|
if(obj->isType(_tp_super)){
|
||||||
|
const PyVar* root = &obj;
|
||||||
|
int depth = 1;
|
||||||
|
while(true){
|
||||||
|
root = &std::get<PyVar>((*root)->_native);
|
||||||
|
if(!(*root)->isType(_tp_super)) break;
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
cls = (*root)->_type.get();
|
||||||
|
for(int i=0; i<depth; i++) cls = cls->attribs[__base__].get();
|
||||||
|
|
||||||
|
it = (*root)->attribs.find(name);
|
||||||
|
if(it != (*root)->attribs.end()) return it->second;
|
||||||
|
}else{
|
||||||
|
it = obj->attribs.find(name);
|
||||||
|
if(it != obj->attribs.end()) return it->second;
|
||||||
|
cls = obj->_type.get();
|
||||||
|
}
|
||||||
|
|
||||||
PyObject* cls = obj->_type.get();
|
|
||||||
while(cls != None.get()) {
|
while(cls != None.get()) {
|
||||||
it = cls->attribs.find(name);
|
it = cls->attribs.find(name);
|
||||||
if(it != cls->attribs.end()){
|
if(it != cls->attribs.end()){
|
||||||
PyVar valueFromCls = it->second;
|
PyVar valueFromCls = it->second;
|
||||||
if(valueFromCls->isType(_tp_function) || valueFromCls->isType(_tp_native_function)){
|
if(valueFromCls->isType(_tp_function) || valueFromCls->isType(_tp_native_function)){
|
||||||
return PyBoundedMethod({obj, valueFromCls});
|
return PyBoundedMethod({obj, std::move(valueFromCls)});
|
||||||
}else{
|
}else{
|
||||||
return valueFromCls;
|
return valueFromCls;
|
||||||
}
|
}
|
||||||
@ -609,12 +627,30 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void setAttr(PyVar& obj, const _Str& name, const PyVar& value) {
|
inline void setAttr(PyVar& obj, const _Str& name, const PyVar& value) {
|
||||||
|
if(obj->isType(_tp_super)){
|
||||||
|
const PyVar* root = &obj;
|
||||||
|
while(true){
|
||||||
|
root = &std::get<PyVar>((*root)->_native);
|
||||||
|
if(!(*root)->isType(_tp_super)) break;
|
||||||
|
}
|
||||||
|
(*root)->attribs[name] = value;
|
||||||
|
}else{
|
||||||
obj->attribs[name] = value;
|
obj->attribs[name] = value;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void setAttr(PyVar& obj, const _Str& name, PyVar&& value) {
|
inline void setAttr(PyVar& obj, const _Str& name, PyVar&& value) {
|
||||||
|
if(obj->isType(_tp_super)){
|
||||||
|
const PyVar* root = &obj;
|
||||||
|
while(true){
|
||||||
|
root = &std::get<PyVar>((*root)->_native);
|
||||||
|
if(!(*root)->isType(_tp_super)) break;
|
||||||
|
}
|
||||||
|
(*root)->attribs[name] = std::move(value);
|
||||||
|
}else{
|
||||||
obj->attribs[name] = std::move(value);
|
obj->attribs[name] = std::move(value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void bindMethod(_Str typeName, _Str funcName, _CppFunc fn) {
|
void bindMethod(_Str typeName, _Str funcName, _CppFunc fn) {
|
||||||
funcName.intern();
|
funcName.intern();
|
||||||
@ -690,7 +726,7 @@ public:
|
|||||||
PyVar _tp_list, _tp_tuple;
|
PyVar _tp_list, _tp_tuple;
|
||||||
PyVar _tp_function, _tp_native_function, _tp_native_iterator, _tp_bounded_method;
|
PyVar _tp_function, _tp_native_function, _tp_native_iterator, _tp_bounded_method;
|
||||||
PyVar _tp_slice, _tp_range, _tp_module, _tp_pointer;
|
PyVar _tp_slice, _tp_range, _tp_module, _tp_pointer;
|
||||||
PyVar _tp_user_pointer;
|
PyVar _tp_user_pointer, _tp_super;
|
||||||
|
|
||||||
__DEF_PY_POOL(Int, _Int, _tp_int, 256);
|
__DEF_PY_POOL(Int, _Int, _tp_int, 256);
|
||||||
__DEF_PY_AS_C(Int, _Int, _tp_int)
|
__DEF_PY_AS_C(Int, _Int, _tp_int)
|
||||||
@ -744,6 +780,7 @@ public:
|
|||||||
_tp_native_function = newClassType("_native_function");
|
_tp_native_function = newClassType("_native_function");
|
||||||
_tp_native_iterator = newClassType("_native_iterator");
|
_tp_native_iterator = newClassType("_native_iterator");
|
||||||
_tp_bounded_method = newClassType("_bounded_method");
|
_tp_bounded_method = newClassType("_bounded_method");
|
||||||
|
_tp_super = newClassType("super");
|
||||||
|
|
||||||
this->None = newObject(_types["NoneType"], (_Int)0);
|
this->None = newObject(_types["NoneType"], (_Int)0);
|
||||||
this->Ellipsis = newObject(_types["ellipsis"], (_Int)0);
|
this->Ellipsis = newObject(_types["ellipsis"], (_Int)0);
|
||||||
|
67
tests/class.py
Normal file
67
tests/class.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
class A:
|
||||||
|
def __init__(self, a, b):
|
||||||
|
self.a = a
|
||||||
|
self.b = b
|
||||||
|
|
||||||
|
def add(self):
|
||||||
|
return self.a + self.b
|
||||||
|
|
||||||
|
def sub(self):
|
||||||
|
return self.a - self.b
|
||||||
|
|
||||||
|
a = A(1, 2)
|
||||||
|
assert a.add() == 3
|
||||||
|
assert a.sub() == -1
|
||||||
|
|
||||||
|
assert a.__base__ is object
|
||||||
|
|
||||||
|
class B(A):
|
||||||
|
def __init__(self, a, b, c):
|
||||||
|
super().__init__(a, b)
|
||||||
|
self.c = c
|
||||||
|
|
||||||
|
def add(self):
|
||||||
|
return self.a + self.b + self.c
|
||||||
|
|
||||||
|
def sub(self):
|
||||||
|
return self.a - self.b - self.c
|
||||||
|
|
||||||
|
assert B.__base__ is A
|
||||||
|
|
||||||
|
b = B(1, 2, 3)
|
||||||
|
assert b.add() == 6
|
||||||
|
assert b.sub() == -4
|
||||||
|
|
||||||
|
class C(B):
|
||||||
|
def __init__(self, a, b, c, d):
|
||||||
|
super().__init__(a, b, c)
|
||||||
|
self.d = d
|
||||||
|
|
||||||
|
def add(self):
|
||||||
|
return self.a + self.b + self.c + self.d
|
||||||
|
|
||||||
|
def sub(self):
|
||||||
|
return self.a - self.b - self.c - self.d
|
||||||
|
|
||||||
|
assert C.__base__ is B
|
||||||
|
|
||||||
|
c = C(1, 2, 3, 4)
|
||||||
|
assert c.add() == 10
|
||||||
|
assert c.sub() == -8
|
||||||
|
|
||||||
|
class D(C):
|
||||||
|
def __init__(self, a, b, c, d, e):
|
||||||
|
super().__init__(a, b, c, d)
|
||||||
|
self.e = e
|
||||||
|
|
||||||
|
def add(self):
|
||||||
|
return super().add() + self.e
|
||||||
|
|
||||||
|
def sub(self):
|
||||||
|
return super().sub() - self.e
|
||||||
|
|
||||||
|
assert D.__base__ is C
|
||||||
|
|
||||||
|
d = D(1, 2, 3, 4, 5)
|
||||||
|
assert d.add() == 15
|
||||||
|
assert d.sub() == -13
|
Loading…
x
Reference in New Issue
Block a user