diff --git a/include/pocketpy/interpreter/vm.h b/include/pocketpy/interpreter/vm.h index 8fc4257b..fd720667 100644 --- a/include/pocketpy/interpreter/vm.h +++ b/include/pocketpy/interpreter/vm.h @@ -10,6 +10,10 @@ // 1. __eq__ and __ne__ fallbacks // 2. un-cleared exception detection // 3. super() +// 4. stack balance guanrantee +// 5. stack effect of each opcode +// 6. py_TypeInfo +// 7. Direct assignment of py_NIL, py_True, py_False, py_None. They are slow. typedef struct py_TypeInfo { py_Name name; diff --git a/src/public/internal.c b/src/public/internal.c index 45817dab..019a27b6 100644 --- a/src/public/internal.c +++ b/src/public/internal.c @@ -78,7 +78,6 @@ void py_sys_setargv(int argc, char** argv) { py_Callbacks* py_getcallbacks() { return &pk_current_vm->callbacks; } - const char* pk_opname(Opcode op) { const static char* OP_NAMES[] = { #define OPCODE(name) #name, @@ -140,6 +139,19 @@ bool py_pushmethod(py_Name name) { bool pk_loadmethod(py_StackRef self, py_Name name) { // NOTE: `out` and `out_self` may overlap with `self` + + if(name == __new__ && py_istype(self, tp_type)) { + // __new__ acts like a @staticmethod + // T.__new__(...) + py_Ref cls_var = py_tpfindmagic(py_totype(self), name); + if(cls_var) { + self[0] = *cls_var; + self[1] = *py_NIL; + return true; + } + return false; + } + py_Type type; // handle super() proxy if(py_istype(self, tp_super)) { diff --git a/src/public/py_ops.c b/src/public/py_ops.c index cd41aff4..770804e4 100644 --- a/src/public/py_ops.c +++ b/src/public/py_ops.c @@ -129,10 +129,12 @@ bool py_getattr(py_Ref self, py_Name name) { // bound method is non-data descriptor switch(cls_var->type) { case tp_function: { + if(name == __new__) goto __STATIC_NEW; py_newboundmethod(py_retval(), self, cls_var); return true; } case tp_nativefunc: { + if(name == __new__) goto __STATIC_NEW; py_newboundmethod(py_retval(), self, cls_var); return true; } @@ -145,6 +147,7 @@ bool py_getattr(py_Ref self, py_Name name) { return true; } default: { + __STATIC_NEW: py_assign(py_retval(), cls_var); return true; } @@ -152,7 +155,7 @@ bool py_getattr(py_Ref self, py_Name name) { } py_Ref fallback = py_tpfindmagic(type, __getattr__); - if(fallback){ + if(fallback) { py_push(fallback); py_push(self); py_newstr(py_pushtmp(), py_name2str(name)); diff --git a/tests/99_bugs.py b/tests/99_bugs.py index 568e166b..80924f49 100644 --- a/tests/99_bugs.py +++ b/tests/99_bugs.py @@ -134,3 +134,6 @@ a = [1, 10, 3] a[test()] += 1 assert (a == [1, 11, 3]), a assert (g == 1), g + +assert list.__new__(list) == [] +assert a.__new__ == list.__new__