blueloveTH 2 лет назад
Родитель
Сommit
e5fb7a65ff
6 измененных файлов с 128 добавлено и 114 удалено
  1. 57 60
      src/ceval.h
  2. 9 9
      src/linalg.h
  3. 1 1
      src/obj.h
  4. 29 19
      src/pocketpy.h
  5. 2 4
      src/str.h
  6. 30 21
      src/vm.h

+ 57 - 60
src/ceval.h

@@ -68,7 +68,7 @@ __NEXT_STEP:;
     TARGET(ROT_TWO) std::swap(TOP(), SECOND()); DISPATCH();
     TARGET(ROT_TWO) std::swap(TOP(), SECOND()); DISPATCH();
     TARGET(PRINT_EXPR)
     TARGET(PRINT_EXPR)
         if(TOP() != None){
         if(TOP() != None){
-            _stdout(this, CAST(Str&, asRepr(TOP())));
+            _stdout(this, CAST(Str&, py_repr(TOP())));
             _stdout(this, "\n");
             _stdout(this, "\n");
         }
         }
         POP();
         POP();
@@ -220,7 +220,12 @@ __NEXT_STEP:;
     TARGET(DELETE_SUBSCR)
     TARGET(DELETE_SUBSCR)
         _1 = POPX();
         _1 = POPX();
         _0 = POPX();
         _0 = POPX();
-        call_method(_0, __delitem__, _1);
+        _ti = _inst_type_info(_0);
+        if(_ti->m__delitem__){
+            _ti->m__delitem__(this, _0, _1);
+        }else{
+            call_method(_0, __delitem__, _1);
+        }
         DISPATCH();
         DISPATCH();
     /*****************************************/
     /*****************************************/
     TARGET(BUILD_LIST)
     TARGET(BUILD_LIST)
@@ -229,16 +234,16 @@ __NEXT_STEP:;
         PUSH(_0);
         PUSH(_0);
         DISPATCH();
         DISPATCH();
     TARGET(BUILD_DICT)
     TARGET(BUILD_DICT)
-        const static StrName m_dict("dict");
+        DEF_SNAME(dict);
         _0 = VAR(STACK_VIEW(byte.arg).to_tuple());
         _0 = VAR(STACK_VIEW(byte.arg).to_tuple());
-        _0 = call(builtins->attr(m_dict), _0);
+        _0 = call(builtins->attr(dict), _0);
         STACK_SHRINK(byte.arg);
         STACK_SHRINK(byte.arg);
         PUSH(_0);
         PUSH(_0);
         DISPATCH();
         DISPATCH();
     TARGET(BUILD_SET)
     TARGET(BUILD_SET)
-        const static StrName m_set("set");
+        DEF_SNAME(set);
         _0 = VAR(STACK_VIEW(byte.arg).to_tuple());
         _0 = VAR(STACK_VIEW(byte.arg).to_tuple());
-        _0 = call(builtins->attr(m_set), _0);
+        _0 = call(builtins->attr(set), _0);
         STACK_SHRINK(byte.arg);
         STACK_SHRINK(byte.arg);
         PUSH(_0);
         PUSH(_0);
         DISPATCH();
         DISPATCH();
@@ -256,58 +261,47 @@ __NEXT_STEP:;
     TARGET(BUILD_STRING) {
     TARGET(BUILD_STRING) {
         std::stringstream ss;
         std::stringstream ss;
         ArgsView view = STACK_VIEW(byte.arg);
         ArgsView view = STACK_VIEW(byte.arg);
-        for(PyObject* obj : view) ss << CAST(Str&, asStr(obj));
+        for(PyObject* obj : view) ss << CAST(Str&, py_str(obj));
         STACK_SHRINK(byte.arg);
         STACK_SHRINK(byte.arg);
         PUSH(VAR(ss.str()));
         PUSH(VAR(ss.str()));
     } DISPATCH();
     } DISPATCH();
     /*****************************************/
     /*****************************************/
-    TARGET(BINARY_TRUEDIV)
-        _1 = POPX();
-        _0 = TOP();
-        if(is_float(_0)){
-            TOP() = VAR(_CAST(f64, _0) / num_to_float(_1));
-        }else{
-            TOP() = call_method(_0, __truediv__, _1);
+#define BINARY_OP_SPECIAL(func)                         \
+        _1 = POPX();                                    \
+        _0 = TOP();                                     \
+        _ti = _inst_type_info(_0);                      \
+        if(_ti->m##func){                               \
+            TOP() = VAR(_ti->m##func(this, _0, _1));    \
+        }else{                                          \
+            TOP() = call_method(_0, func, _1);          \
         }
         }
+
+    TARGET(BINARY_TRUEDIV)
+        BINARY_OP_SPECIAL(__truediv__);
         DISPATCH();
         DISPATCH();
     TARGET(BINARY_POW)
     TARGET(BINARY_POW)
-        _1 = POPX();
-        _0 = TOP();
-        TOP() = call_method(_0, __pow__, _1);
+        BINARY_OP_SPECIAL(__pow__);
         DISPATCH();
         DISPATCH();
-
-#define INT_BINARY_OP(op, func)                             \
-        if(is_both_int(TOP(), SECOND())){                   \
-            i64 b = _CAST(i64, TOP());                      \
-            i64 a = _CAST(i64, SECOND());                   \
-            POP();                                          \
-            TOP() = VAR(a op b);                            \
-        }else{                                              \
-            _1 = POPX();                                    \
-            _0 = TOP();                                     \
-            TOP() = call_method(_0, func, _1);              \
-        }
-
     TARGET(BINARY_ADD)
     TARGET(BINARY_ADD)
-        INT_BINARY_OP(+, __add__)
+        BINARY_OP_SPECIAL(__add__);
         DISPATCH()
         DISPATCH()
     TARGET(BINARY_SUB)
     TARGET(BINARY_SUB)
-        INT_BINARY_OP(-, __sub__)
+        BINARY_OP_SPECIAL(__sub__);
         DISPATCH()
         DISPATCH()
     TARGET(BINARY_MUL)
     TARGET(BINARY_MUL)
-        INT_BINARY_OP(*, __mul__)
+        BINARY_OP_SPECIAL(__mul__);
         DISPATCH()
         DISPATCH()
     TARGET(BINARY_FLOORDIV)
     TARGET(BINARY_FLOORDIV)
-        INT_BINARY_OP(/, __floordiv__)
+        BINARY_OP_SPECIAL(__floordiv__);
         DISPATCH()
         DISPATCH()
     TARGET(BINARY_MOD)
     TARGET(BINARY_MOD)
-        INT_BINARY_OP(%, __mod__)
+        BINARY_OP_SPECIAL(__mod__);
         DISPATCH()
         DISPATCH()
     TARGET(COMPARE_LT)
     TARGET(COMPARE_LT)
-        INT_BINARY_OP(<, __lt__)
+        BINARY_OP_SPECIAL(__lt__);
         DISPATCH()
         DISPATCH()
     TARGET(COMPARE_LE)
     TARGET(COMPARE_LE)
-        INT_BINARY_OP(<=, __le__)
+        BINARY_OP_SPECIAL(__le__);
         DISPATCH()
         DISPATCH()
     TARGET(COMPARE_EQ)
     TARGET(COMPARE_EQ)
         _1 = POPX();
         _1 = POPX();
@@ -320,34 +314,32 @@ __NEXT_STEP:;
         TOP() = VAR(py_not_equals(_0, _1));
         TOP() = VAR(py_not_equals(_0, _1));
         DISPATCH()
         DISPATCH()
     TARGET(COMPARE_GT)
     TARGET(COMPARE_GT)
-        INT_BINARY_OP(>, __gt__)
+        BINARY_OP_SPECIAL(__gt__);
         DISPATCH()
         DISPATCH()
     TARGET(COMPARE_GE)
     TARGET(COMPARE_GE)
-        INT_BINARY_OP(>=, __ge__)
+        BINARY_OP_SPECIAL(__ge__);
         DISPATCH()
         DISPATCH()
     TARGET(BITWISE_LSHIFT)
     TARGET(BITWISE_LSHIFT)
-        INT_BINARY_OP(<<, __lshift__)
+        BINARY_OP_SPECIAL(__lshift__);
         DISPATCH()
         DISPATCH()
     TARGET(BITWISE_RSHIFT)
     TARGET(BITWISE_RSHIFT)
-        INT_BINARY_OP(>>, __rshift__)
+        BINARY_OP_SPECIAL(__rshift__);
         DISPATCH()
         DISPATCH()
     TARGET(BITWISE_AND)
     TARGET(BITWISE_AND)
-        INT_BINARY_OP(&, __and__)
+        BINARY_OP_SPECIAL(__and__);
         DISPATCH()
         DISPATCH()
     TARGET(BITWISE_OR)
     TARGET(BITWISE_OR)
-        INT_BINARY_OP(|, __or__)
+        BINARY_OP_SPECIAL(__or__);
         DISPATCH()
         DISPATCH()
     TARGET(BITWISE_XOR)
     TARGET(BITWISE_XOR)
-        INT_BINARY_OP(^, __xor__)
+        BINARY_OP_SPECIAL(__xor__);
         DISPATCH()
         DISPATCH()
-#undef INT_BINARY_OP
-
     TARGET(BINARY_MATMUL)
     TARGET(BINARY_MATMUL)
-        _1 = POPX();
-        _0 = TOP();
-        TOP() = call_method(_0, __matmul__, _1);
+        BINARY_OP_SPECIAL(__matmul__);
         DISPATCH();
         DISPATCH();
 
 
+#undef BINARY_OP_SPECIAL
+
     TARGET(IS_OP)
     TARGET(IS_OP)
         _1 = POPX();    // rhs
         _1 = POPX();    // rhs
         _0 = TOP();     // lhs
         _0 = TOP();     // lhs
@@ -359,7 +351,12 @@ __NEXT_STEP:;
         DISPATCH();
         DISPATCH();
     TARGET(CONTAINS_OP)
     TARGET(CONTAINS_OP)
         // a in b -> b __contains__ a
         // a in b -> b __contains__ a
-        _0 = call_method(TOP(), __contains__, SECOND());
+        _ti = _inst_type_info(TOP());
+        if(_ti->m__contains__){
+            _0 = VAR(_ti->m__contains__(this, TOP(), SECOND()));
+        }else{
+            _0 = call_method(TOP(), __contains__, SECOND());
+        }
         POP();
         POP();
         if(byte.arg == 1){
         if(byte.arg == 1){
             TOP() = VAR(!CAST(bool, _0));
             TOP() = VAR(!CAST(bool, _0));
@@ -430,9 +427,9 @@ __NEXT_STEP:;
         call_method(SECOND(), __setitem__, t[0], t[1]);
         call_method(SECOND(), __setitem__, t[0], t[1]);
     } DISPATCH();
     } DISPATCH();
     TARGET(SET_ADD)
     TARGET(SET_ADD)
-        const static StrName m_add("add");
+        DEF_SNAME(add);
         _0 = POPX();
         _0 = POPX();
-        call_method(SECOND(), m_add, _0);
+        call_method(SECOND(), add, _0);
         DISPATCH();
         DISPATCH();
     /*****************************************/
     /*****************************************/
     TARGET(UNARY_NEGATIVE)
     TARGET(UNARY_NEGATIVE)
@@ -443,7 +440,7 @@ __NEXT_STEP:;
         DISPATCH();
         DISPATCH();
     /*****************************************/
     /*****************************************/
     TARGET(GET_ITER)
     TARGET(GET_ITER)
-        TOP() = asIter(TOP());
+        TOP() = py_iter(TOP());
         DISPATCH();
         DISPATCH();
     TARGET(FOR_ITER)
     TARGET(FOR_ITER)
         _0 = PyIterNext(TOP());
         _0 = PyIterNext(TOP());
@@ -489,7 +486,7 @@ __NEXT_STEP:;
     TARGET(UNPACK_SEQUENCE)
     TARGET(UNPACK_SEQUENCE)
     TARGET(UNPACK_EX) {
     TARGET(UNPACK_EX) {
         auto _lock = heap.gc_scope_lock();  // lock the gc via RAII!!
         auto _lock = heap.gc_scope_lock();  // lock the gc via RAII!!
-        _0 = asIter(POPX());
+        _0 = py_iter(POPX());
         for(int i=0; i<byte.arg; i++){
         for(int i=0; i<byte.arg; i++){
             _1 = PyIterNext(_0);
             _1 = PyIterNext(_0);
             if(_1 == StopIteration) ValueError("not enough values to unpack");
             if(_1 == StopIteration) ValueError("not enough values to unpack");
@@ -510,7 +507,7 @@ __NEXT_STEP:;
     } DISPATCH();
     } DISPATCH();
     TARGET(UNPACK_UNLIMITED) {
     TARGET(UNPACK_UNLIMITED) {
         auto _lock = heap.gc_scope_lock();  // lock the gc via RAII!!
         auto _lock = heap.gc_scope_lock();  // lock the gc via RAII!!
-        _0 = asIter(POPX());
+        _0 = py_iter(POPX());
         _1 = PyIterNext(_0);
         _1 = PyIterNext(_0);
         while(_1 != StopIteration){
         while(_1 != StopIteration){
             PUSH(_1);
             PUSH(_1);
@@ -538,11 +535,11 @@ __NEXT_STEP:;
     /*****************************************/
     /*****************************************/
     // TODO: using "goto" inside with block may cause __exit__ not called
     // TODO: using "goto" inside with block may cause __exit__ not called
     TARGET(WITH_ENTER)
     TARGET(WITH_ENTER)
-        const static StrName __enter__("__enter__");
+        DEF_SNAME(__enter__);
         call_method(POPX(), __enter__);
         call_method(POPX(), __enter__);
         DISPATCH();
         DISPATCH();
     TARGET(WITH_EXIT)
     TARGET(WITH_EXIT)
-        const static StrName __exit__("__exit__");
+        DEF_SNAME(__exit__);
         call_method(POPX(), __exit__);
         call_method(POPX(), __exit__);
         DISPATCH();
         DISPATCH();
     /*****************************************/
     /*****************************************/
@@ -553,7 +550,7 @@ __NEXT_STEP:;
             auto& t = CAST(Tuple&, _0);
             auto& t = CAST(Tuple&, _0);
             if(t.size() != 2) ValueError("assert tuple must have 2 elements");
             if(t.size() != 2) ValueError("assert tuple must have 2 elements");
             _0 = t[0];
             _0 = t[0];
-            msg = CAST(Str&, asStr(t[1]));
+            msg = CAST(Str&, py_str(t[1]));
         }
         }
         bool ok = asBool(_0);
         bool ok = asBool(_0);
         POP();
         POP();
@@ -566,13 +563,13 @@ __NEXT_STEP:;
     } DISPATCH();
     } DISPATCH();
     TARGET(RAISE) {
     TARGET(RAISE) {
         _0 = POPX();
         _0 = POPX();
-        Str msg = _0 == None ? "" : CAST(Str, asStr(_0));
+        Str msg = _0 == None ? "" : CAST(Str, py_str(_0));
         _error(StrName(byte.arg), msg);
         _error(StrName(byte.arg), msg);
     } DISPATCH();
     } DISPATCH();
     TARGET(RE_RAISE) _raise(); DISPATCH();
     TARGET(RE_RAISE) _raise(); DISPATCH();
     /*****************************************/
     /*****************************************/
     TARGET(SETUP_DOCSTRING)
     TARGET(SETUP_DOCSTRING)
-        const static StrName __doc__("__doc__");
+        DEF_SNAME(__doc__);
         TOP()->attr().set(__doc__, co_consts[byte.arg]);
         TOP()->attr().set(__doc__, co_consts[byte.arg]);
         DISPATCH();
         DISPATCH();
     TARGET(FORMAT_STRING) {
     TARGET(FORMAT_STRING) {

+ 9 - 9
src/linalg.h

@@ -347,8 +347,8 @@ struct PyVec2: Vec2 {
             return VAR(Vec2(x, y));
             return VAR(Vec2(x, y));
         });
         });
 
 
-        vm->bind_method<0>(type, "__repr__", [](VM* vm, ArgsView args){
-            PyVec2& self = _CAST(PyVec2&, args[0]);
+        vm->bind__repr__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
+            PyVec2& self = _CAST(PyVec2&, obj);
             std::stringstream ss;
             std::stringstream ss;
             ss << "vec2(" << self.x << ", " << self.y << ")";
             ss << "vec2(" << self.x << ", " << self.y << ")";
             return VAR(ss.str());
             return VAR(ss.str());
@@ -397,8 +397,8 @@ struct PyVec3: Vec3 {
             return VAR(Vec3(x, y, z));
             return VAR(Vec3(x, y, z));
         });
         });
 
 
-        vm->bind_method<0>(type, "__repr__", [](VM* vm, ArgsView args){
-            PyVec3& self = _CAST(PyVec3&, args[0]);
+        vm->bind__repr__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
+            PyVec3& self = _CAST(PyVec3&, obj);
             std::stringstream ss;
             std::stringstream ss;
             ss << "vec3(" << self.x << ", " << self.y << ", " << self.z << ")";
             ss << "vec3(" << self.x << ", " << self.y << ", " << self.z << ")";
             return VAR(ss.str());
             return VAR(ss.str());
@@ -471,8 +471,8 @@ struct PyMat3x3: Mat3x3{
 
 
 #undef METHOD_PROXY_NONE
 #undef METHOD_PROXY_NONE
 
 
-        vm->bind_method<0>(type, "__repr__", [](VM* vm, ArgsView args){
-            PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
+        vm->bind__repr__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
+            PyMat3x3& self = _CAST(PyMat3x3&, obj);
             std::stringstream ss;
             std::stringstream ss;
             ss << std::fixed << std::setprecision(4);
             ss << std::fixed << std::setprecision(4);
             ss << "mat3x3([[" << self._11 << ", " << self._12 << ", " << self._13 << "],\n";
             ss << "mat3x3([[" << self._11 << ", " << self._12 << ", " << self._13 << "],\n";
@@ -486,9 +486,9 @@ struct PyMat3x3: Mat3x3{
             return VAR_T(PyMat3x3, self);
             return VAR_T(PyMat3x3, self);
         });
         });
 
 
-        vm->bind_method<1>(type, "__getitem__", [](VM* vm, ArgsView args){
-            PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
-            Tuple& t = CAST(Tuple&, args[1]);
+        vm->bind__getitem__(OBJ_GET(Type, type), [](VM* vm, PyObject* obj, PyObject* index){
+            PyMat3x3& self = _CAST(PyMat3x3&, obj);
+            Tuple& t = CAST(Tuple&, index);
             if(t.size() != 2){
             if(t.size() != 2){
                 vm->TypeError("Mat3x3.__getitem__ takes a tuple of 2 integers");
                 vm->TypeError("Mat3x3.__getitem__ takes a tuple of 2 integers");
                 return vm->None;
                 return vm->None;

+ 1 - 1
src/obj.h

@@ -187,7 +187,7 @@ Str obj_type_name(VM* vm, Type type);
 #if DEBUG_NO_BUILTIN_MODULES
 #if DEBUG_NO_BUILTIN_MODULES
 #define OBJ_NAME(obj) Str("<?>")
 #define OBJ_NAME(obj) Str("<?>")
 #else
 #else
-const static StrName __name__("__name__");
+DEF_SNAME(__name__);
 #define OBJ_NAME(obj) OBJ_GET(Str, vm->getattr(obj, __name__))
 #define OBJ_NAME(obj) OBJ_GET(Str, vm->getattr(obj, __name__))
 #endif
 #endif
 
 

+ 29 - 19
src/pocketpy.h

@@ -58,8 +58,8 @@ inline void init_builtins(VM* _vm) {
         return false;                                                       \
         return false;                                                       \
     });                                                                     \
     });                                                                     \
     _vm->bind##name(_vm->tp_float, [](VM* vm, PyObject* lhs, PyObject* rhs) {   \
     _vm->bind##name(_vm->tp_float, [](VM* vm, PyObject* lhs, PyObject* rhs) {   \
-        if(is_int(rhs))     return _CAST(f64, lhs) == _CAST(i64, rhs);          \
-        if(is_float(rhs))   return _CAST(f64, lhs) == _CAST(f64, rhs);          \
+        if(is_int(rhs))     return _CAST(f64, lhs) op _CAST(i64, rhs);          \
+        if(is_float(rhs))   return _CAST(f64, lhs) op _CAST(f64, rhs);          \
         if constexpr(is_eq) return lhs op rhs;                                  \
         if constexpr(is_eq) return lhs op rhs;                                  \
         vm->TypeError("unsupported operand type(s) for " #op );                 \
         vm->TypeError("unsupported operand type(s) for " #op );                 \
         return false;                                                           \
         return false;                                                           \
@@ -131,7 +131,7 @@ inline void init_builtins(VM* _vm) {
         return vm->None;
         return vm->None;
     });
     });
 
 
-    _vm->bind_builtin_func<1>("repr", CPP_LAMBDA(vm->asRepr(args[0])));
+    _vm->bind_builtin_func<1>("repr", CPP_LAMBDA(vm->py_repr(args[0])));
 
 
     _vm->bind_builtin_func<1>("len", [](VM* vm, ArgsView args){
     _vm->bind_builtin_func<1>("len", [](VM* vm, ArgsView args){
         const PyTypeInfo* ti = vm->_inst_type_info(args[0]);
         const PyTypeInfo* ti = vm->_inst_type_info(args[0]);
@@ -140,7 +140,7 @@ inline void init_builtins(VM* _vm) {
     });
     });
 
 
     _vm->bind_builtin_func<1>("hash", [](VM* vm, ArgsView args){
     _vm->bind_builtin_func<1>("hash", [](VM* vm, ArgsView args){
-        i64 value = vm->py_hash(args[0]);
+        i64 value = vm->hash(args[0]);
         if(((value << 2) >> 2) != value) value >>= 2;
         if(((value << 2) >> 2) != value) value >>= 2;
         return VAR(value);
         return VAR(value);
     });
     });
@@ -178,7 +178,7 @@ inline void init_builtins(VM* _vm) {
     });
     });
 
 
     _vm->bind_builtin_func<1>("iter", [](VM* vm, ArgsView args) {
     _vm->bind_builtin_func<1>("iter", [](VM* vm, ArgsView args) {
-        return vm->asIter(args[0]);
+        return vm->py_iter(args[0]);
     });
     });
 
 
     _vm->bind_builtin_func<1>("next", [](VM* vm, ArgsView args) {
     _vm->bind_builtin_func<1>("next", [](VM* vm, ArgsView args) {
@@ -199,8 +199,9 @@ inline void init_builtins(VM* _vm) {
         return VAR(std::move(ret));
         return VAR(std::move(ret));
     });
     });
 
 
-    _vm->bind__repr__(_vm->tp_object, [](VM* vm, PyObject* self) {
-        if(is_tagged(self)) self = nullptr;
+    _vm->bind__repr__(_vm->tp_object, [](VM* vm, PyObject* obj) {
+        PyObject* self = obj;
+        if(is_tagged(obj)) self = nullptr;
         std::stringstream ss;
         std::stringstream ss;
         ss << "<" << OBJ_NAME(vm->_t(self)) << " object at " << std::hex << self << ">";
         ss << "<" << OBJ_NAME(vm->_t(self)) << " object at " << std::hex << self << ">";
         return VAR(ss.str());
         return VAR(ss.str());
@@ -356,7 +357,7 @@ inline void init_builtins(VM* _vm) {
     });
     });
 
 
     /************ PyString ************/
     /************ PyString ************/
-    _vm->bind_constructor<2>("str", CPP_LAMBDA(vm->asStr(args[1])));
+    _vm->bind_constructor<2>("str", CPP_LAMBDA(vm->py_str(args[1])));
 
 
     _vm->bind__hash__(_vm->tp_str, [](VM* vm, PyObject* obj) {
     _vm->bind__hash__(_vm->tp_str, [](VM* vm, PyObject* obj) {
         return (i64)_CAST(Str&, obj).hash();
         return (i64)_CAST(Str&, obj).hash();
@@ -460,7 +461,7 @@ inline void init_builtins(VM* _vm) {
         auto _lock = vm->heap.gc_scope_lock();
         auto _lock = vm->heap.gc_scope_lock();
         const Str& self = _CAST(Str&, args[0]);
         const Str& self = _CAST(Str&, args[0]);
         FastStrStream ss;
         FastStrStream ss;
-        PyObject* it = vm->asIter(args[1]);     // strong ref
+        PyObject* it = vm->py_iter(args[1]);     // strong ref
         PyObject* obj = vm->PyIterNext(it);
         PyObject* obj = vm->PyIterNext(it);
         while(obj != vm->StopIteration){
         while(obj != vm->StopIteration){
             if(!ss.empty()) ss << self;
             if(!ss.empty()) ss << self;
@@ -494,7 +495,7 @@ inline void init_builtins(VM* _vm) {
     _vm->bind_method<1>("list", "extend", [](VM* vm, ArgsView args) {
     _vm->bind_method<1>("list", "extend", [](VM* vm, ArgsView args) {
         auto _lock = vm->heap.gc_scope_lock();
         auto _lock = vm->heap.gc_scope_lock();
         List& self = _CAST(List&, args[0]);
         List& self = _CAST(List&, args[0]);
-        PyObject* it = vm->asIter(args[1]);     // strong ref
+        PyObject* it = vm->py_iter(args[1]);     // strong ref
         PyObject* obj = vm->PyIterNext(it);
         PyObject* obj = vm->PyIterNext(it);
         while(obj != vm->StopIteration){
         while(obj != vm->StopIteration){
             self.push_back(obj);
             self.push_back(obj);
@@ -578,7 +579,7 @@ inline void init_builtins(VM* _vm) {
         i64 x = 1000003;
         i64 x = 1000003;
         const Tuple& items = CAST(Tuple&, obj);
         const Tuple& items = CAST(Tuple&, obj);
         for (int i=0; i<items.size(); i++) {
         for (int i=0; i<items.size(); i++) {
-            i64 y = vm->py_hash(items[i]);
+            i64 y = vm->hash(items[i]);
             // recommended by Github Copilot
             // recommended by Github Copilot
             x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2));
             x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2));
         }
         }
@@ -617,7 +618,12 @@ inline void init_builtins(VM* _vm) {
     _vm->bind__xor__(_vm->tp_bool, [](VM* vm, PyObject* lhs, PyObject* rhs) {
     _vm->bind__xor__(_vm->tp_bool, [](VM* vm, PyObject* lhs, PyObject* rhs) {
         return VAR(_CAST(bool, lhs) != CAST(bool, rhs));
         return VAR(_CAST(bool, lhs) != CAST(bool, rhs));
     });
     });
-
+    _vm->bind__eq__(_vm->tp_bool, [](VM* vm, PyObject* lhs, PyObject* rhs) {
+        return _CAST(bool, lhs) == CAST(bool, rhs);
+    });
+    _vm->bind__ne__(_vm->tp_bool, [](VM* vm, PyObject* lhs, PyObject* rhs) {
+        return _CAST(bool, lhs) != CAST(bool, rhs);
+    });
     _vm->bind__repr__(_vm->_type("ellipsis"), [](VM* vm, PyObject* self) {
     _vm->bind__repr__(_vm->_type("ellipsis"), [](VM* vm, PyObject* self) {
         return VAR("Ellipsis");
         return VAR("Ellipsis");
     });
     });
@@ -697,9 +703,9 @@ inline void init_builtins(VM* _vm) {
         const Slice& self = _CAST(Slice&, obj);
         const Slice& self = _CAST(Slice&, obj);
         std::stringstream ss;
         std::stringstream ss;
         ss << "slice(";
         ss << "slice(";
-        ss << CAST(Str, vm->asRepr(self.start)) << ", ";
-        ss << CAST(Str, vm->asRepr(self.stop)) << ", ";
-        ss << CAST(Str, vm->asRepr(self.step)) << ")";
+        ss << CAST(Str, vm->py_repr(self.start)) << ", ";
+        ss << CAST(Str, vm->py_repr(self.stop)) << ", ";
+        ss << CAST(Str, vm->py_repr(self.step)) << ")";
         return VAR(ss.str());
         return VAR(ss.str());
     });
     });
 
 
@@ -748,7 +754,7 @@ inline void init_builtins(VM* _vm) {
         for(auto& item : self.attr().items()){
         for(auto& item : self.attr().items()){
             if(!first) ss << ", ";
             if(!first) ss << ", ";
             first = false;
             first = false;
-            ss << item.first.escape() << ": " << CAST(Str, vm->asRepr(item.second));
+            ss << item.first.escape() << ": " << CAST(Str, vm->py_repr(item.second));
         }
         }
         ss << "})";
         ss << "})";
         return VAR(ss.str());
         return VAR(ss.str());
@@ -818,7 +824,11 @@ inline void add_module_json(VM* vm){
         return vm->_exec(code, vm->top_frame()->_module);
         return vm->_exec(code, vm->top_frame()->_module);
     });
     });
 
 
-    vm->bind_func<1>(mod, "dumps", CPP_LAMBDA(vm->call_method(args[0], __json__)));
+    vm->bind_func<1>(mod, "dumps", [](VM* vm, ArgsView args) {
+        const PyTypeInfo* ti = vm->_inst_type_info(args[0]);
+        if(ti->m__json__) return ti->m__json__(vm, args[0]);
+        return vm->call_method(args[0], __json__);
+    });
 }
 }
 
 
 
 
@@ -1129,7 +1139,7 @@ extern "C" {
         pkpy::PyObject* val = vm->_main->attr().try_get(name);
         pkpy::PyObject* val = vm->_main->attr().try_get(name);
         if(val == nullptr) return nullptr;
         if(val == nullptr) return nullptr;
         try{
         try{
-            pkpy::Str repr = pkpy::CAST(pkpy::Str&, vm->asRepr(val));
+            pkpy::Str repr = pkpy::CAST(pkpy::Str&, vm->py_repr(val));
             return repr.c_str_dup();
             return repr.c_str_dup();
         }catch(...){
         }catch(...){
             return nullptr;
             return nullptr;
@@ -1141,7 +1151,7 @@ extern "C" {
         pkpy::PyObject* ret = vm->exec(source, "<eval>", pkpy::EVAL_MODE);
         pkpy::PyObject* ret = vm->exec(source, "<eval>", pkpy::EVAL_MODE);
         if(ret == nullptr) return nullptr;
         if(ret == nullptr) return nullptr;
         try{
         try{
-            pkpy::Str repr = pkpy::CAST(pkpy::Str&, vm->asRepr(ret));
+            pkpy::Str repr = pkpy::CAST(pkpy::Str&, vm->py_repr(ret));
             return repr.c_str_dup();
             return repr.c_str_dup();
         }catch(...){
         }catch(...){
             return nullptr;
             return nullptr;

+ 2 - 4
src/str.h

@@ -387,7 +387,6 @@ const StrName __next__ = StrName::get("__next__");      // unused
 const StrName __json__ = StrName::get("__json__");
 const StrName __json__ = StrName::get("__json__");
 const StrName __neg__ = StrName::get("__neg__");        // unused
 const StrName __neg__ = StrName::get("__neg__");        // unused
 const StrName __bool__ = StrName::get("__bool__");      // unused
 const StrName __bool__ = StrName::get("__bool__");      // unused
-
 // logical operators
 // logical operators
 const StrName __eq__ = StrName::get("__eq__");
 const StrName __eq__ = StrName::get("__eq__");
 const StrName __ne__ = StrName::get("__ne__");
 const StrName __ne__ = StrName::get("__ne__");
@@ -396,7 +395,6 @@ const StrName __le__ = StrName::get("__le__");
 const StrName __gt__ = StrName::get("__gt__");
 const StrName __gt__ = StrName::get("__gt__");
 const StrName __ge__ = StrName::get("__ge__");
 const StrName __ge__ = StrName::get("__ge__");
 const StrName __contains__ = StrName::get("__contains__");
 const StrName __contains__ = StrName::get("__contains__");
-
 // binary operators
 // binary operators
 const StrName __add__ = StrName::get("__add__");
 const StrName __add__ = StrName::get("__add__");
 const StrName __sub__ = StrName::get("__sub__");
 const StrName __sub__ = StrName::get("__sub__");
@@ -406,16 +404,16 @@ const StrName __floordiv__ = StrName::get("__floordiv__");
 const StrName __mod__ = StrName::get("__mod__");
 const StrName __mod__ = StrName::get("__mod__");
 const StrName __pow__ = StrName::get("__pow__");
 const StrName __pow__ = StrName::get("__pow__");
 const StrName __matmul__ = StrName::get("__matmul__");
 const StrName __matmul__ = StrName::get("__matmul__");
-
 const StrName __lshift__ = StrName::get("__lshift__");
 const StrName __lshift__ = StrName::get("__lshift__");
 const StrName __rshift__ = StrName::get("__rshift__");
 const StrName __rshift__ = StrName::get("__rshift__");
 const StrName __and__ = StrName::get("__and__");
 const StrName __and__ = StrName::get("__and__");
 const StrName __or__ = StrName::get("__or__");
 const StrName __or__ = StrName::get("__or__");
 const StrName __xor__ = StrName::get("__xor__");
 const StrName __xor__ = StrName::get("__xor__");
-
 // indexer
 // indexer
 const StrName __getitem__ = StrName::get("__getitem__");
 const StrName __getitem__ = StrName::get("__getitem__");
 const StrName __setitem__ = StrName::get("__setitem__");
 const StrName __setitem__ = StrName::get("__setitem__");
 const StrName __delitem__ = StrName::get("__delitem__");
 const StrName __delitem__ = StrName::get("__delitem__");
 
 
+#define DEF_SNAME(name) const static StrName name(#name)
+
 } // namespace pkpy
 } // namespace pkpy

+ 30 - 21
src/vm.h

@@ -166,15 +166,25 @@ public:
         return FrameId(&callstack.data(), callstack.size()-1);
         return FrameId(&callstack.data(), callstack.size()-1);
     }
     }
 
 
-    PyObject* asStr(PyObject* obj){
+    PyObject* py_str(PyObject* obj){
+        const PyTypeInfo* ti = _inst_type_info(obj);
+        if(ti->m__str__) return ti->m__str__(this, obj);
         PyObject* self;
         PyObject* self;
         PyObject* f = get_unbound_method(obj, __str__, &self, false);
         PyObject* f = get_unbound_method(obj, __str__, &self, false);
         if(self != PY_NULL) return call_method(self, f);
         if(self != PY_NULL) return call_method(self, f);
-        return asRepr(obj);
+        return py_repr(obj);
     }
     }
 
 
-    PyObject* asIter(PyObject* obj){
+    PyObject* py_repr(PyObject* obj){
+        const PyTypeInfo* ti = _inst_type_info(obj);
+        if(ti->m__repr__) return ti->m__repr__(this, obj);
+        return call_method(obj, __repr__);
+    }
+
+    PyObject* py_iter(PyObject* obj){
         if(is_type(obj, tp_iterator)) return obj;
         if(is_type(obj, tp_iterator)) return obj;
+        const PyTypeInfo* ti = _inst_type_info(obj);
+        if(ti->m__iter__) return ti->m__iter__(this, obj);
         PyObject* self;
         PyObject* self;
         PyObject* iter_f = get_unbound_method(obj, __iter__, &self, false);
         PyObject* iter_f = get_unbound_method(obj, __iter__, &self, false);
         if(self != PY_NULL) return call_method(self, iter_f);
         if(self != PY_NULL) return call_method(self, iter_f);
@@ -300,11 +310,11 @@ public:
 
 
     PyObject* _find_type_object(const Str& type){
     PyObject* _find_type_object(const Str& type){
         PyObject* obj = builtins->attr().try_get(type);
         PyObject* obj = builtins->attr().try_get(type);
-        check_non_tagged_type(obj, tp_type);
         if(obj == nullptr){
         if(obj == nullptr){
             for(auto& t: _all_types) if(t.name == type) return t.obj;
             for(auto& t: _all_types) if(t.name == type) return t.obj;
             throw std::runtime_error(fmt("type not found: ", type));
             throw std::runtime_error(fmt("type not found: ", type));
         }
         }
+        check_non_tagged_type(obj, tp_type);
         return obj;
         return obj;
     }
     }
 
 
@@ -560,8 +570,7 @@ public:
     PyObject* num_negated(PyObject* obj);
     PyObject* num_negated(PyObject* obj);
     f64 num_to_float(PyObject* obj);
     f64 num_to_float(PyObject* obj);
     bool asBool(PyObject* obj);
     bool asBool(PyObject* obj);
-    i64 py_hash(PyObject* obj);
-    PyObject* asRepr(PyObject*);
+    i64 hash(PyObject* obj);
     PyObject* asList(PyObject*);
     PyObject* asList(PyObject*);
     PyObject* new_module(StrName name);
     PyObject* new_module(StrName name);
     Str disassemble(CodeObject_ co);
     Str disassemble(CodeObject_ co);
@@ -713,6 +722,10 @@ inline PyObject* py_var(VM* vm, NoReturn val){
     return vm->None;
     return vm->None;
 }
 }
 
 
+inline PyObject* py_var(VM* vm, PyObject* val){
+    return val;
+}
+
 inline PyObject* VM::num_negated(PyObject* obj){
 inline PyObject* VM::num_negated(PyObject* obj){
     if (is_int(obj)){
     if (is_int(obj)){
         return VAR(-CAST(i64, obj));
         return VAR(-CAST(i64, obj));
@@ -749,7 +762,7 @@ inline bool VM::asBool(PyObject* obj){
 
 
 inline PyObject* VM::asList(PyObject* it){
 inline PyObject* VM::asList(PyObject* it){
     auto _lock = heap.gc_scope_lock();
     auto _lock = heap.gc_scope_lock();
-    it = asIter(it);
+    it = py_iter(it);
     List list;
     List list;
     PyObject* obj = PyIterNext(it);
     PyObject* obj = PyIterNext(it);
     while(obj != StopIteration){
     while(obj != StopIteration){
@@ -801,19 +814,15 @@ inline void VM::parse_int_slice(const Slice& s, int length, int& start, int& sto
     }
     }
 }
 }
 
 
-inline i64 VM::py_hash(PyObject* obj){
+inline i64 VM::hash(PyObject* obj){
     const PyTypeInfo* ti = _inst_type_info(obj);
     const PyTypeInfo* ti = _inst_type_info(obj);
     if(ti->m__hash__) return ti->m__hash__(this, obj);
     if(ti->m__hash__) return ti->m__hash__(this, obj);
     PyObject* ret = call_method(obj, __hash__);
     PyObject* ret = call_method(obj, __hash__);
     return CAST(i64, ret);
     return CAST(i64, ret);
 }
 }
 
 
-inline PyObject* VM::asRepr(PyObject* obj){
-    return call_method(obj, __repr__);
-}
-
 inline PyObject* VM::format(Str spec, PyObject* obj){
 inline PyObject* VM::format(Str spec, PyObject* obj){
-    if(spec.empty()) return asStr(obj);
+    if(spec.empty()) return py_str(obj);
     char type;
     char type;
     switch(spec.end()[-1]){
     switch(spec.end()[-1]){
         case 'f': case 'd': case 's':
         case 'f': case 'd': case 's':
@@ -867,7 +876,7 @@ inline PyObject* VM::format(Str spec, PyObject* obj){
     }else if(type == 's'){
     }else if(type == 's'){
         ret = CAST(Str&, obj);
         ret = CAST(Str&, obj);
     }else{
     }else{
-        ret = CAST(Str&, asStr(obj));
+        ret = CAST(Str&, py_str(obj));
     }
     }
     if(width > ret.length()){
     if(width > ret.length()){
         int pad = width - ret.length();
         int pad = width - ret.length();
@@ -893,7 +902,7 @@ inline std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){
     switch(byte.op){
     switch(byte.op){
         case OP_LOAD_CONST:
         case OP_LOAD_CONST:
             if(vm != nullptr){
             if(vm != nullptr){
-                argStr += fmt(" (", CAST(Str, vm->asRepr(co->consts[byte.arg])), ")");
+                argStr += fmt(" (", CAST(Str, vm->py_repr(co->consts[byte.arg])), ")");
             }
             }
             break;
             break;
         case OP_LOAD_NAME: case OP_LOAD_GLOBAL: case OP_LOAD_NONLOCAL: case OP_STORE_GLOBAL:
         case OP_LOAD_NAME: case OP_LOAD_GLOBAL: case OP_LOAD_NONLOCAL: case OP_STORE_GLOBAL:
@@ -1117,7 +1126,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
         if(method_call) FATAL_ERROR();
         if(method_call) FATAL_ERROR();
         // [type, NULL, args..., kwargs...]
         // [type, NULL, args..., kwargs...]
 
 
-        const static StrName __new__("__new__");
+        DEF_SNAME(__new__);
         PyObject* new_f = find_name_in_mro(callable, __new__);
         PyObject* new_f = find_name_in_mro(callable, __new__);
         PyObject* obj;
         PyObject* obj;
         if(new_f != nullptr){
         if(new_f != nullptr){
@@ -1136,7 +1145,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
 
 
         // __init__
         // __init__
         PyObject* self;
         PyObject* self;
-        const static StrName __init__("__init__");
+        DEF_SNAME(__init__);
         callable = get_unbound_method(obj, __init__, &self, false);
         callable = get_unbound_method(obj, __init__, &self, false);
         if (self != PY_NULL) {
         if (self != PY_NULL) {
             // replace `NULL` with `self`
             // replace `NULL` with `self`
@@ -1155,7 +1164,7 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
 
 
     // handle `__call__` overload
     // handle `__call__` overload
     PyObject* self;
     PyObject* self;
-    const static StrName __call__("__call__");
+    DEF_SNAME(__call__);
     PyObject* call_f = get_unbound_method(callable, __call__, &self, false);
     PyObject* call_f = get_unbound_method(callable, __call__, &self, false);
     if(self != PY_NULL){
     if(self != PY_NULL){
         p1[-(ARGC + 2)] = call_f;
         p1[-(ARGC + 2)] = call_f;
@@ -1245,8 +1254,8 @@ inline PyObject* VM::_py_call(PyObject** p0, PyObject* callable, ArgsView args,
     return nullptr;
     return nullptr;
 }
 }
 
 
-const static StrName __get__("__get__");
-const static StrName __set__("__set__");
+DEF_SNAME(__get__);
+DEF_SNAME(__set__);
 
 
 // https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance
 // https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance
 inline PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){
 inline PyObject* VM::getattr(PyObject* obj, StrName name, bool throw_err){
@@ -1424,7 +1433,7 @@ inline void VM::bind__len__(Type type, i64 (*f)(VM* vm, PyObject*)){
 
 
 inline void Dict::_probe(PyObject *key, bool &ok, int &i) const{
 inline void Dict::_probe(PyObject *key, bool &ok, int &i) const{
     ok = false;
     ok = false;
-    i = vm->py_hash(key) & _mask;
+    i = vm->hash(key) & _mask;
     while(_items[i].first != nullptr) {
     while(_items[i].first != nullptr) {
         if(vm->py_equals(_items[i].first, key)) { ok = true; break; }
         if(vm->py_equals(_items[i].first, key)) { ok = true; break; }
         i = (i + 1) & _mask;
         i = (i + 1) & _mask;