blueloveTH 1 gadu atpakaļ
vecāks
revīzija
857b798172

+ 3 - 12
build_g.sh

@@ -2,19 +2,10 @@ set -e
 
 python prebuild.py
 
-SRC_C=$(find src/ -name "*.c")
-SRC_CPP=$(find src/ -name "*.cpp")
+SRC=$(find src/ -name "*.c")
 
-COMMON_FLAGS="-Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1" # -fsanitize=address,leak,undefined"
-
-FLAGS_C="-std=c11 $COMMON_FLAGS"
-FLAGS_CPP="-std=c++17 -stdlib=libc++ -frtti $COMMON_FLAGS"
+FLAGS="-std=c11 -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1" # -fsanitize=address,leak,undefined"
 
 echo "Compiling C files..."
-clang $FLAGS_C -c $SRC_C
-ar rcs libpocketpy_c.a *.o
-rm *.o
+clang $FLAGS $SRC src2/main.c -o main
 
-echo "Compiling C++ files..."
-clang++ $FLAGS_CPP -o main src2/main.cpp $SRC_CPP libpocketpy_c.a 
-rm libpocketpy_c.a

+ 0 - 1
include/pocketpy/interpreter/gc.h

@@ -1,5 +1,4 @@
 #include "pocketpy/objects/object.h"
-#include "pocketpy/objects/public.h"
 #include "pocketpy/common/config.h"
 
 #ifdef __cplusplus

+ 2 - 2
include/pocketpy/objects/error.h

@@ -17,7 +17,7 @@ typedef struct pkpy_ExceptionFrame {
 } pkpy_ExceptionFrame;
 
 typedef struct pkpy_Exception {
-    pk_StrName type;
+    StrName type;
     pkpy_Str msg;
     bool is_re;
 
@@ -29,7 +29,7 @@ typedef struct pkpy_Exception {
     c11_vector/*T=pkpy_ExceptionFrame*/ stacktrace;
 } pkpy_Exception;
 
-void pkpy_Exception__ctor(pkpy_Exception* self, pk_StrName type);
+void pkpy_Exception__ctor(pkpy_Exception* self, StrName type);
 void pkpy_Exception__dtor(pkpy_Exception* self);
 void pkpy_Exception__stpush(pkpy_Exception* self, pkpy_SourceData_ src, int lineno, const char* cursor, const char* name);
 pkpy_Str pkpy_Exception__summary(pkpy_Exception* self);

+ 1 - 1
include/pocketpy/objects/object.h

@@ -32,7 +32,7 @@ PK_INLINE PyVar PyVar__fromobj(PyObject* obj){
     PyVar retval = {
         .type = obj->type,
         .is_ptr = true,
-        ._obj = obj;
+        ._obj = obj
     };
     return retval;
 }

+ 1 - 1
src/error.c

@@ -2,7 +2,7 @@
 #include "pocketpy/common/strname.h"
 #include "pocketpy/common/sstream.h"
 
-void pkpy_Exception__ctor(pkpy_Exception* self, pk_StrName type){
+void pkpy_Exception__ctor(pkpy_Exception* self, StrName type){
     self->type = type;
     self->is_re = true;
     self->_ip_on_error = -1;

+ 1127 - 1127
src/interpreter/ceval.c

@@ -1,1151 +1,1151 @@
-#include "pocketpy/interpreter/ceval.hpp"
-#include "pocketpy/objects/base.h"
+// #include "pocketpy/interpreter/ceval.h"
+// #include "pocketpy/objects/base.h"
 
-namespace pkpy {
+// namespace pkpy {
 
-#define PREDICT_INT_OP(op)                                                                                             \
-    if(is_int(_0) && is_int(_1)) {                                                                                     \
-        TOP() = VAR(_0._i64 op _1._i64);                                                                     \
-        DISPATCH()                                                                                                     \
-    }
+// #define PREDICT_INT_OP(op)                                                                                             \
+//     if(is_int(_0) && is_int(_1)) {                                                                                     \
+//         TOP() = VAR(_0._i64 op _1._i64);                                                                     \
+//         DISPATCH()                                                                                                     \
+//     }
 
-#define PREDICT_INT_DIV_OP(op)                                                                                         \
-    if(is_int(_0) && is_int(_1)) {                                                                                     \
-        i64 divisor = _1._i64;                                                                                    \
-        if(divisor == 0) ZeroDivisionError();                                                                          \
-        TOP() = VAR(_0._i64 op divisor);                                                                          \
-        DISPATCH()                                                                                                     \
-    }
+// #define PREDICT_INT_DIV_OP(op)                                                                                         \
+//     if(is_int(_0) && is_int(_1)) {                                                                                     \
+//         i64 divisor = _1._i64;                                                                                    \
+//         if(divisor == 0) ZeroDivisionError();                                                                          \
+//         TOP() = VAR(_0._i64 op divisor);                                                                          \
+//         DISPATCH()                                                                                                     \
+//     }
 
-#define BINARY_F_COMPARE(func, op, rfunc)                                                                              \
-    PyVar ret;                                                                                                         \
-    const PyTypeInfo* _ti = _tp_info(_0);                                                                              \
-    if(_ti->m##func) {                                                                                                 \
-        ret = _ti->m##func(this, _0, _1);                                                                              \
-    } else {                                                                                                           \
-        PyVar self;                                                                                                    \
-        PyVar _2 = get_unbound_method(_0, func, &self, false);                                                         \
-        if(_2.type)                                                                                              \
-            ret = call_method(self, _2, _1);                                                                           \
-        else                                                                                                           \
-            ret = NotImplemented;                                                                                      \
-    }                                                                                                                  \
-    if(is_not_implemented(ret)) {                                                                                      \
-        PyVar self;                                                                                                    \
-        PyVar _2 = get_unbound_method(_1, rfunc, &self, false);                                                        \
-        if(_2.type)                                                                                              \
-            ret = call_method(self, _2, _0);                                                                           \
-        else                                                                                                           \
-            BinaryOptError(op, _0, _1);                                                                                \
-        if(is_not_implemented(ret)) BinaryOptError(op, _0, _1);                                                        \
-    }
+// #define BINARY_F_COMPARE(func, op, rfunc)                                                                              \
+//     PyVar ret;                                                                                                         \
+//     const PyTypeInfo* _ti = _tp_info(_0);                                                                              \
+//     if(_ti->m##func) {                                                                                                 \
+//         ret = _ti->m##func(this, _0, _1);                                                                              \
+//     } else {                                                                                                           \
+//         PyVar self;                                                                                                    \
+//         PyVar _2 = get_unbound_method(_0, func, &self, false);                                                         \
+//         if(_2.type)                                                                                              \
+//             ret = call_method(self, _2, _1);                                                                           \
+//         else                                                                                                           \
+//             ret = NotImplemented;                                                                                      \
+//     }                                                                                                                  \
+//     if(is_not_implemented(ret)) {                                                                                      \
+//         PyVar self;                                                                                                    \
+//         PyVar _2 = get_unbound_method(_1, rfunc, &self, false);                                                        \
+//         if(_2.type)                                                                                              \
+//             ret = call_method(self, _2, _0);                                                                           \
+//         else                                                                                                           \
+//             BinaryOptError(op, _0, _1);                                                                                \
+//         if(is_not_implemented(ret)) BinaryOptError(op, _0, _1);                                                        \
+//     }
 
-void VM::__op_unpack_sequence(uint16_t arg) {
-    PyVar _0 = POPX();
-    if(is_type(_0, VM::tp_tuple)) {
-        // fast path for tuple
-        Tuple& tuple = PK_OBJ_GET(Tuple, _0);
-        if(tuple.size() == arg) {
-            for(PyVar obj: tuple)
-                PUSH(obj);
-        } else {
-            ValueError(_S("expected ", (int)arg, " values to unpack, got ", (int)tuple.size()));
-        }
-    } else {
-        auto _lock = gc_scope_lock();  // lock the gc via RAII!!
-        _0 = py_iter(_0);
-        const PyTypeInfo* ti = _tp_info(_0);
-        for(int i = 0; i < arg; i++) {
-            PyVar _1 = _py_next(ti, _0);
-            if(_1 == StopIteration) ValueError("not enough values to unpack");
-            PUSH(_1);
-        }
-        if(_py_next(ti, _0) != StopIteration) ValueError("too many values to unpack");
-    }
-}
+// void VM::__op_unpack_sequence(uint16_t arg) {
+//     PyVar _0 = POPX();
+//     if(is_type(_0, VM::tp_tuple)) {
+//         // fast path for tuple
+//         Tuple& tuple = PK_OBJ_GET(Tuple, _0);
+//         if(tuple.size() == arg) {
+//             for(PyVar obj: tuple)
+//                 PUSH(obj);
+//         } else {
+//             ValueError(_S("expected ", (int)arg, " values to unpack, got ", (int)tuple.size()));
+//         }
+//     } else {
+//         auto _lock = gc_scope_lock();  // lock the gc via RAII!!
+//         _0 = py_iter(_0);
+//         const PyTypeInfo* ti = _tp_info(_0);
+//         for(int i = 0; i < arg; i++) {
+//             PyVar _1 = _py_next(ti, _0);
+//             if(_1 == StopIteration) ValueError("not enough values to unpack");
+//             PUSH(_1);
+//         }
+//         if(_py_next(ti, _0) != StopIteration) ValueError("too many values to unpack");
+//     }
+// }
 
-bool VM::py_lt(PyVar _0, PyVar _1) {
-    BINARY_F_COMPARE(__lt__, "<", __gt__);
-    assert(ret.type == tp_bool);
-    return ret.extra;
-}
+// bool VM::py_lt(PyVar _0, PyVar _1) {
+//     BINARY_F_COMPARE(__lt__, "<", __gt__);
+//     assert(ret.type == tp_bool);
+//     return ret.extra;
+// }
 
-bool VM::py_le(PyVar _0, PyVar _1) {
-    BINARY_F_COMPARE(__le__, "<=", __ge__);
-    assert(ret.type == tp_bool);
-    return ret.extra;
-}
+// bool VM::py_le(PyVar _0, PyVar _1) {
+//     BINARY_F_COMPARE(__le__, "<=", __ge__);
+//     assert(ret.type == tp_bool);
+//     return ret.extra;
+// }
 
-bool VM::py_gt(PyVar _0, PyVar _1) {
-    BINARY_F_COMPARE(__gt__, ">", __lt__);
-    assert(ret.type == tp_bool);
-    return ret.extra;
-}
+// bool VM::py_gt(PyVar _0, PyVar _1) {
+//     BINARY_F_COMPARE(__gt__, ">", __lt__);
+//     assert(ret.type == tp_bool);
+//     return ret.extra;
+// }
 
-bool VM::py_ge(PyVar _0, PyVar _1) {
-    BINARY_F_COMPARE(__ge__, ">=", __le__);
-    assert(ret.type == tp_bool);
-    return ret.extra;
-}
+// bool VM::py_ge(PyVar _0, PyVar _1) {
+//     BINARY_F_COMPARE(__ge__, ">=", __le__);
+//     assert(ret.type == tp_bool);
+//     return ret.extra;
+// }
 
-#undef BINARY_F_COMPARE
+// #undef BINARY_F_COMPARE
 
-#if PK_ENABLE_PROFILER
-#define CEVAL_STEP_CALLBACK()                                                                                          \
-    if(_ceval_on_step) _ceval_on_step(this, frame, byte);                                                              \
-    if(_profiler) _profiler->_step(callstack.size(), frame);                                                           \
-    if(!_next_breakpoint.empty()) { _next_breakpoint._step(this); }
-#else
-#define CEVAL_STEP_CALLBACK()                                                                                          \
-    if(_ceval_on_step && _ceval_on_step) {                                                                             \
-        if(_ceval_on_step)                                                                                             \
-            if(_ceval_on_step) _ceval_on_step(this, frame, byte);                                                      \
-    }
-#endif
+// #if PK_ENABLE_PROFILER
+// #define CEVAL_STEP_CALLBACK()                                                                                          \
+//     if(_ceval_on_step) _ceval_on_step(this, frame, byte);                                                              \
+//     if(_profiler) _profiler->_step(callstack.size(), frame);                                                           \
+//     if(!_next_breakpoint.empty()) { _next_breakpoint._step(this); }
+// #else
+// #define CEVAL_STEP_CALLBACK()                                                                                          \
+//     if(_ceval_on_step && _ceval_on_step) {                                                                             \
+//         if(_ceval_on_step)                                                                                             \
+//             if(_ceval_on_step) _ceval_on_step(this, frame, byte);                                                      \
+//     }
+// #endif
 
-#define DISPATCH()                                                                                                     \
-    {                                                                                                                  \
-        frame->_ip++;                                                                                                  \
-        goto __NEXT_STEP;                                                                                              \
-    }
-#define DISPATCH_JUMP(__offset)                                                                                        \
-    {                                                                                                                  \
-        frame->_ip += __offset;                                                                                        \
-        goto __NEXT_STEP;                                                                                              \
-    }
-#define DISPATCH_JUMP_ABSOLUTE(__target)                                                                               \
-    {                                                                                                                  \
-        frame->_ip = c11__at(Bytecode, &frame->co->codes, __target);                                                   \
-        goto __NEXT_STEP;                                                                                              \
-    }
+// #define DISPATCH()                                                                                                     \
+//     {                                                                                                                  \
+//         frame->_ip++;                                                                                                  \
+//         goto __NEXT_STEP;                                                                                              \
+//     }
+// #define DISPATCH_JUMP(__offset)                                                                                        \
+//     {                                                                                                                  \
+//         frame->_ip += __offset;                                                                                        \
+//         goto __NEXT_STEP;                                                                                              \
+//     }
+// #define DISPATCH_JUMP_ABSOLUTE(__target)                                                                               \
+//     {                                                                                                                  \
+//         frame->_ip = c11__at(Bytecode, &frame->co->codes, __target);                                                   \
+//         goto __NEXT_STEP;                                                                                              \
+//     }
 
-PyVar VM::__run_top_frame() {
-    Frame* frame = &callstack.top();
-    const Frame* base_frame = frame;
-    InternalException __internal_exception;
+// PyVar VM::__run_top_frame() {
+//     Frame* frame = &callstack.top();
+//     const Frame* base_frame = frame;
+//     InternalException __internal_exception;
 
-    while(true) {
-        try {
-            /**********************************************************************/
-            {
-            __NEXT_FRAME:
-                Bytecode byte;
+//     while(true) {
+//         try {
+//             /**********************************************************************/
+//             {
+//             __NEXT_FRAME:
+//                 Bytecode byte;
 
-                if(__internal_exception.type == InternalExceptionType::Null) {
-                    // None
-                    frame->_ip++;
-                } else if(__internal_exception.type == InternalExceptionType::Handled) {
-                    // HandledException + continue
-                    frame->_ip = c11__at(Bytecode, &frame->co->codes, __internal_exception.arg);
-                    __internal_exception = {};
-                } else {
-                    // UnhandledException + continue (need_raise = true)
-                    // ToBeRaisedException + continue (need_raise = true)
-                    __internal_exception = {};
-                    __raise_exc();  // no return
-                }
+//                 if(__internal_exception.type == InternalExceptionType::Null) {
+//                     // None
+//                     frame->_ip++;
+//                 } else if(__internal_exception.type == InternalExceptionType::Handled) {
+//                     // HandledException + continue
+//                     frame->_ip = c11__at(Bytecode, &frame->co->codes, __internal_exception.arg);
+//                     __internal_exception = {};
+//                 } else {
+//                     // UnhandledException + continue (need_raise = true)
+//                     // ToBeRaisedException + continue (need_raise = true)
+//                     __internal_exception = {};
+//                     __raise_exc();  // no return
+//                 }
 
-            __NEXT_STEP:
-                byte = *frame->_ip;
-                CEVAL_STEP_CALLBACK()
+//             __NEXT_STEP:
+//                 byte = *frame->_ip;
+//                 CEVAL_STEP_CALLBACK()
 
-#if PK_DEBUG_CEVAL_STEP
-                __log_s_data();
-#endif
-                switch((Opcode)byte.op) {
-                    case OP_NO_OP: DISPATCH()
-                    /*****************************************/
-                    case OP_POP_TOP: POP(); DISPATCH()
-                    case OP_DUP_TOP: PUSH(TOP()); DISPATCH()
-                    case OP_DUP_TOP_TWO:
-                        // [a, b]
-                        PUSH(SECOND());  // [a, b, a]
-                        PUSH(SECOND());  // [a, b, a, b]
-                        DISPATCH()
-                    case OP_ROT_TWO: std::swap(TOP(), SECOND()); DISPATCH()
-                    case OP_ROT_THREE: {
-                        // [a, b, c] -> [c, a, b]
-                        PyVar _0 = TOP();
-                        TOP() = SECOND();
-                        SECOND() = THIRD();
-                        THIRD() = _0;
-                    }
-                        DISPATCH()
-                    case OP_PRINT_EXPR:
-                        if(!is_none(TOP())) stdout_write(py_repr(TOP()) + "\n");
-                        POP();
-                        DISPATCH()
-                    /*****************************************/
-                    case OP_LOAD_CONST:
-                        PUSH(c11__getitem(PyVar, &frame->co->consts, byte.arg));
-                        DISPATCH()
-                    case OP_LOAD_NONE: PUSH(None); DISPATCH()
-                    case OP_LOAD_TRUE: PUSH(True); DISPATCH()
-                    case OP_LOAD_FALSE: PUSH(False); DISPATCH()
-                    /*****************************************/
-                    case OP_LOAD_SMALL_INT: s_data.emplace(tp_int, (i64)(int16_t)byte.arg); DISPATCH()
-                    /*****************************************/
-                    case OP_LOAD_ELLIPSIS: PUSH(Ellipsis); DISPATCH()
-                    case OP_LOAD_FUNCTION: {
-                        FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg);
-                        PyVar obj;
-                        if(decl->nested) {
-                            NameDict* captured = frame->_locals.to_namedict();
-                            obj = new_object<Function>(tp_function, decl, frame->_module, nullptr, captured);
-                            uint16_t name = pk_StrName__map2(pkpy_Str__sv(&decl->code->name));
-                            captured->set(name, obj);
-                        } else {
-                            obj = new_object<Function>(tp_function, decl, frame->_module, nullptr, nullptr);
-                        }
-                        PUSH(obj);
-                    }
-                        DISPATCH()
-                    case OP_LOAD_NULL: PUSH(PY_NULL); DISPATCH()
-                    /*****************************************/
-                    case OP_LOAD_FAST: {
-                        PyVar _0 = frame->_locals[byte.arg];
-                        if(_0 == PY_NULL) vm->UnboundLocalError(c11__getitem(uint16_t, &frame->co->varnames, byte.arg));
-                        PUSH(_0);
-                    }
-                        DISPATCH()
-                    case OP_LOAD_NAME: {
-                        StrName _name(byte.arg);
-                        PyVar* slot = frame->_locals.try_get_name(_name);
-                        if(slot != nullptr) {
-                            if(*slot == PY_NULL) vm->UnboundLocalError(_name);
-                            PUSH(*slot);
-                            DISPATCH()
-                        }
-                        PyVar* _0 = frame->f_closure_try_get(_name);
-                        if(_0 != nullptr) {
-                            PUSH(*_0);
-                            DISPATCH()
-                        }
-                        _0 = frame->f_globals().try_get_2_likely_found(_name);
-                        if(_0 != nullptr) {
-                            PUSH(*_0);
-                            DISPATCH()
-                        }
-                        _0 = vm->builtins->attr().try_get_2_likely_found(_name);
-                        if(_0 != nullptr) {
-                            PUSH(*_0);
-                            DISPATCH()
-                        }
-                        vm->NameError(_name);
-                    }
-                        DISPATCH()
-                    case OP_LOAD_NONLOCAL: {
-                        StrName _name(byte.arg);
-                        PyVar* _0 = frame->f_closure_try_get(_name);
-                        if(_0 != nullptr) {
-                            PUSH(*_0);
-                            DISPATCH()
-                        }
-                        _0 = frame->f_globals().try_get_2_likely_found(_name);
-                        if(_0 != nullptr) {
-                            PUSH(*_0);
-                            DISPATCH()
-                        }
-                        _0 = vm->builtins->attr().try_get_2_likely_found(_name);
-                        if(_0 != nullptr) {
-                            PUSH(*_0);
-                            DISPATCH()
-                        }
-                        vm->NameError(_name);
-                    }
-                        DISPATCH()
-                    case OP_LOAD_GLOBAL: {
-                        StrName _name(byte.arg);
-                        PyVar _0 = frame->f_globals().try_get_likely_found(_name);
-                        if(_0 != nullptr) {
-                            PUSH(_0);
-                            DISPATCH()
-                        }
-                        _0 = vm->builtins->attr().try_get_likely_found(_name);
-                        if(_0 != nullptr) {
-                            PUSH(_0);
-                            DISPATCH()
-                        }
-                        vm->NameError(_name);
-                    }
-                        DISPATCH()
-                    case OP_LOAD_ATTR: {
-                        TOP() = getattr(TOP(), StrName(byte.arg));
-                    }
-                        DISPATCH()
-                    case OP_LOAD_CLASS_GLOBAL: {
-                        assert(__curr_class != nullptr);
-                        StrName _name(byte.arg);
-                        PyVar _0 = getattr(__curr_class, _name, false);
-                        if(_0 != nullptr) {
-                            PUSH(_0);
-                            DISPATCH()
-                        }
-                        // load global if attribute not found
-                        _0 = frame->f_globals().try_get_likely_found(_name);
-                        if(_0 != nullptr) {
-                            PUSH(_0);
-                            DISPATCH()
-                        }
-                        _0 = vm->builtins->attr().try_get_likely_found(_name);
-                        if(_0 != nullptr) {
-                            PUSH(_0);
-                            DISPATCH()
-                        }
-                        vm->NameError(_name);
-                    }
-                        DISPATCH()
-                    case OP_LOAD_METHOD: {
-                        PyVar _0;
-                        TOP() = get_unbound_method(TOP(), StrName(byte.arg), &_0, true, true);
-                        PUSH(_0);
-                    }
-                        DISPATCH()
-                    case OP_LOAD_SUBSCR: {
-                        PyVar _1 = POPX();  // b
-                        PyVar _0 = TOP();   // a
-                        auto _ti = _tp_info(_0);
-                        if(_ti->m__getitem__) {
-                            TOP() = _ti->m__getitem__(this, _0, _1);
-                        } else {
-                            TOP() = call_method(_0, __getitem__, _1);
-                        }
-                    }
-                        DISPATCH()
-                    case OP_LOAD_SUBSCR_FAST: {
-                        PyVar _1 = frame->_locals[byte.arg];
-                        if(_1 == PY_NULL) vm->UnboundLocalError(c11__getitem(uint16_t, &frame->co->varnames, byte.arg));
-                        PyVar _0 = TOP();  // a
-                        auto _ti = _tp_info(_0);
-                        if(_ti->m__getitem__) {
-                            TOP() = _ti->m__getitem__(this, _0, _1);
-                        } else {
-                            TOP() = call_method(_0, __getitem__, _1);
-                        }
-                    }
-                        DISPATCH()
-                    case OP_LOAD_SUBSCR_SMALL_INT: {
-                        PyVar _1 = VAR((int16_t)byte.arg);
-                        PyVar _0 = TOP();  // a
-                        auto _ti = _tp_info(_0);
-                        if(_ti->m__getitem__) {
-                            TOP() = _ti->m__getitem__(this, _0, _1);
-                        } else {
-                            TOP() = call_method(_0, __getitem__, _1);
-                        }
-                    }
-                        DISPATCH()
-                    case OP_STORE_FAST: frame->_locals[byte.arg] = POPX(); DISPATCH()
-                    case OP_STORE_NAME: {
-                        StrName _name(byte.arg);
-                        PyVar _0 = POPX();
-                        if(frame->_callable != nullptr) {
-                            PyVar* slot = frame->_locals.try_get_name(_name);
-                            if(slot != nullptr) {
-                                *slot = _0;  // store in locals if possible
-                            } else {
-                                Function& func = frame->_callable->as<Function>();
-                                if(func.decl == __dynamic_func_decl) {
-                                    assert(func._closure != nullptr);
-                                    func._closure->set(_name, _0);
-                                } else {
-                                    vm->NameError(_name);
-                                }
-                            }
-                        } else {
-                            frame->f_globals().set(_name, _0);
-                        }
-                    }
-                        DISPATCH()
-                    case OP_STORE_GLOBAL: frame->f_globals().set(StrName(byte.arg), POPX()); DISPATCH()
-                    case OP_STORE_ATTR: {
-                        PyVar _0 = TOP();     // a
-                        PyVar _1 = SECOND();  // val
-                        setattr(_0, StrName(byte.arg), _1);
-                        STACK_SHRINK(2);
-                    }
-                        DISPATCH()
-                    case OP_STORE_SUBSCR: {
-                        PyVar _2 = POPX();  // b
-                        PyVar _1 = POPX();  // a
-                        PyVar _0 = POPX();  // val
-                        auto _ti = _tp_info(_1);
-                        if(_ti->m__setitem__) {
-                            _ti->m__setitem__(this, _1, _2, _0);
-                        } else {
-                            call_method(_1, __setitem__, _2, _0);
-                        }
-                    }
-                        DISPATCH()
-                    case OP_STORE_SUBSCR_FAST: {
-                        PyVar _2 = frame->_locals[byte.arg];  // b
-                        if(_2 == PY_NULL) vm->UnboundLocalError(c11__getitem(uint16_t, &frame->co->varnames, byte.arg));
-                        PyVar _1 = POPX();  // a
-                        PyVar _0 = POPX();  // val
-                        auto _ti = _tp_info(_1);
-                        if(_ti->m__setitem__) {
-                            _ti->m__setitem__(this, _1, _2, _0);
-                        } else {
-                            call_method(_1, __setitem__, _2, _0);
-                        }
-                    }
-                        DISPATCH()
-                    case OP_DELETE_FAST: {
-                        PyVar _0 = frame->_locals[byte.arg];
-                        if(_0 == PY_NULL) vm->UnboundLocalError(c11__getitem(uint16_t, &frame->co->varnames, byte.arg));
-                        frame->_locals[byte.arg].set_null();
-                    }
-                        DISPATCH()
-                    case OP_DELETE_NAME: {
-                        StrName _name(byte.arg);
-                        if(frame->_callable != nullptr) {
-                            PyVar* slot = frame->_locals.try_get_name(_name);
-                            if(slot != nullptr) {
-                                slot->set_null();
-                            } else {
-                                Function& func = frame->_callable->as<Function>();
-                                if(func.decl == __dynamic_func_decl) {
-                                    assert(func._closure != nullptr);
-                                    bool ok = func._closure->del(_name);
-                                    if(!ok) vm->NameError(_name);
-                                } else {
-                                    vm->NameError(_name);
-                                }
-                            }
-                        } else {
-                            if(!frame->f_globals().del(_name)) vm->NameError(_name);
-                        }
-                    }
-                        DISPATCH()
-                    case OP_DELETE_GLOBAL: {
-                        StrName _name(byte.arg);
-                        if(!frame->f_globals().del(_name)) vm->NameError(_name);
-                    }
-                        DISPATCH()
-                    case OP_DELETE_ATTR: {
-                        PyVar _0 = POPX();
-                        delattr(_0, StrName(byte.arg));
-                    }
-                        DISPATCH()
-                    case OP_DELETE_SUBSCR: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = POPX();
-                        auto _ti = _tp_info(_0);
-                        if(_ti->m__delitem__) {
-                            _ti->m__delitem__(this, _0, _1);
-                        } else {
-                            call_method(_0, __delitem__, _1);
-                        }
-                    }
-                        DISPATCH()
-                    /*****************************************/
-                    case OP_BUILD_LONG: {
-                        PyVar _0 = builtins->attr().try_get_likely_found(pk_id_long);
-                        if(_0 == nullptr) AttributeError(builtins, pk_id_long);
-                        TOP() = call(_0, TOP());
-                    }
-                        DISPATCH()
-                    case OP_BUILD_IMAG: {
-                        PyVar _0 = builtins->attr().try_get_likely_found(pk_id_complex);
-                        if(_0 == nullptr) AttributeError(builtins, pk_id_long);
-                        TOP() = call(_0, VAR(0), TOP());
-                    }
-                        DISPATCH()
-                    case OP_BUILD_BYTES: {
-                        const Str& s = CAST(Str&, TOP());
-                        unsigned char* p = (unsigned char*)std::malloc(s.size);
-                        std::memcpy(p, s.c_str(), s.size);
-                        TOP() = VAR(Bytes(p, s.size));
-                    }
-                        DISPATCH()
-                    case OP_BUILD_TUPLE: {
-                        PyVar _0 = VAR(STACK_VIEW(byte.arg).to_tuple());
-                        STACK_SHRINK(byte.arg);
-                        PUSH(_0);
-                    }
-                        DISPATCH()
-                    case OP_BUILD_LIST: {
-                        PyVar _0 = VAR(STACK_VIEW(byte.arg).to_list());
-                        STACK_SHRINK(byte.arg);
-                        PUSH(_0);
-                    }
-                        DISPATCH()
-                    case OP_BUILD_DICT: {
-                        if(byte.arg == 0) {
-                            PUSH(VAR(Dict()));
-                            DISPATCH()
-                        }
-                        PyVar _0 = VAR(STACK_VIEW(byte.arg).to_list());
-                        _0 = call(_t(tp_dict), _0);
-                        STACK_SHRINK(byte.arg);
-                        PUSH(_0);
-                    }
-                        DISPATCH()
-                    case OP_BUILD_SET: {
-                        PyVar _0 = VAR(STACK_VIEW(byte.arg).to_list());
-                        _0 = call(builtins->attr()[pk_id_set], _0);
-                        STACK_SHRINK(byte.arg);
-                        PUSH(_0);
-                    }
-                        DISPATCH()
-                    case OP_BUILD_SLICE: {
-                        PyVar _2 = POPX();  // step
-                        PyVar _1 = POPX();  // stop
-                        PyVar _0 = POPX();  // start
-                        PUSH(VAR(Slice(_0, _1, _2)));
-                    }
-                        DISPATCH()
-                    case OP_BUILD_STRING: {
-                        SStream ss;
-                        ArgsView view = STACK_VIEW(byte.arg);
-                        for(PyVar obj: view)
-                            ss << py_str(obj);
-                        STACK_SHRINK(byte.arg);
-                        PUSH(VAR(ss.str()));
-                    }
-                        DISPATCH()
-                    /*****************************************/
-                    case OP_BUILD_TUPLE_UNPACK: {
-                        List list;
-                        __unpack_as_list(STACK_VIEW(byte.arg), list);
-                        STACK_SHRINK(byte.arg);
-                        PyVar _0 = VAR(list.to_tuple());
-                        PUSH(_0);
-                    }
-                        DISPATCH()
-                    case OP_BUILD_LIST_UNPACK: {
-                        List list;
-                        __unpack_as_list(STACK_VIEW(byte.arg), list);
-                        STACK_SHRINK(byte.arg);
-                        PyVar _0 = VAR(std::move(list));
-                        PUSH(_0);
-                    }
-                        DISPATCH()
-                    case OP_BUILD_DICT_UNPACK: {
-                        Dict dict;
-                        __unpack_as_dict(STACK_VIEW(byte.arg), dict);
-                        STACK_SHRINK(byte.arg);
-                        PyVar _0 = VAR(std::move(dict));
-                        PUSH(_0);
-                    }
-                        DISPATCH()
-                    case OP_BUILD_SET_UNPACK: {
-                        List list;
-                        __unpack_as_list(STACK_VIEW(byte.arg), list);
-                        STACK_SHRINK(byte.arg);
-                        PyVar _0 = VAR(std::move(list));
-                        _0 = call(builtins->attr()[pk_id_set], _0);
-                        PUSH(_0);
-                    }
-                        DISPATCH()
-                        /*****************************************/
-#define BINARY_OP_SPECIAL(func)                                                                                        \
-    _ti = _tp_info(_0);                                                                                                \
-    if(_ti->m##func) {                                                                                                 \
-        TOP() = _ti->m##func(this, _0, _1);                                                                            \
-    } else {                                                                                                           \
-        PyVar self;                                                                                                    \
-        PyVar _2 = get_unbound_method(_0, func, &self, false);                                                         \
-        if(_2 != nullptr)                                                                                              \
-            TOP() = call_method(self, _2, _1);                                                                         \
-        else                                                                                                           \
-            TOP() = NotImplemented;                                                                                    \
-    }
+// #if PK_DEBUG_CEVAL_STEP
+//                 __log_s_data();
+// #endif
+//                 switch((Opcode)byte.op) {
+//                     case OP_NO_OP: DISPATCH()
+//                     /*****************************************/
+//                     case OP_POP_TOP: POP(); DISPATCH()
+//                     case OP_DUP_TOP: PUSH(TOP()); DISPATCH()
+//                     case OP_DUP_TOP_TWO:
+//                         // [a, b]
+//                         PUSH(SECOND());  // [a, b, a]
+//                         PUSH(SECOND());  // [a, b, a, b]
+//                         DISPATCH()
+//                     case OP_ROT_TWO: std::swap(TOP(), SECOND()); DISPATCH()
+//                     case OP_ROT_THREE: {
+//                         // [a, b, c] -> [c, a, b]
+//                         PyVar _0 = TOP();
+//                         TOP() = SECOND();
+//                         SECOND() = THIRD();
+//                         THIRD() = _0;
+//                     }
+//                         DISPATCH()
+//                     case OP_PRINT_EXPR:
+//                         if(!is_none(TOP())) stdout_write(py_repr(TOP()) + "\n");
+//                         POP();
+//                         DISPATCH()
+//                     /*****************************************/
+//                     case OP_LOAD_CONST:
+//                         PUSH(c11__getitem(PyVar, &frame->co->consts, byte.arg));
+//                         DISPATCH()
+//                     case OP_LOAD_NONE: PUSH(None); DISPATCH()
+//                     case OP_LOAD_TRUE: PUSH(True); DISPATCH()
+//                     case OP_LOAD_FALSE: PUSH(False); DISPATCH()
+//                     /*****************************************/
+//                     case OP_LOAD_SMALL_INT: s_data.emplace(tp_int, (i64)(int16_t)byte.arg); DISPATCH()
+//                     /*****************************************/
+//                     case OP_LOAD_ELLIPSIS: PUSH(Ellipsis); DISPATCH()
+//                     case OP_LOAD_FUNCTION: {
+//                         FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg);
+//                         PyVar obj;
+//                         if(decl->nested) {
+//                             NameDict* captured = frame->_locals.to_namedict();
+//                             obj = new_object<Function>(tp_function, decl, frame->_module, nullptr, captured);
+//                             uint16_t name = pk_StrName__map2(pkpy_Str__sv(&decl->code->name));
+//                             captured->set(name, obj);
+//                         } else {
+//                             obj = new_object<Function>(tp_function, decl, frame->_module, nullptr, nullptr);
+//                         }
+//                         PUSH(obj);
+//                     }
+//                         DISPATCH()
+//                     case OP_LOAD_NULL: PUSH(PY_NULL); DISPATCH()
+//                     /*****************************************/
+//                     case OP_LOAD_FAST: {
+//                         PyVar _0 = frame->_locals[byte.arg];
+//                         if(_0 == PY_NULL) vm->UnboundLocalError(c11__getitem(uint16_t, &frame->co->varnames, byte.arg));
+//                         PUSH(_0);
+//                     }
+//                         DISPATCH()
+//                     case OP_LOAD_NAME: {
+//                         StrName _name(byte.arg);
+//                         PyVar* slot = frame->_locals.try_get_name(_name);
+//                         if(slot != nullptr) {
+//                             if(*slot == PY_NULL) vm->UnboundLocalError(_name);
+//                             PUSH(*slot);
+//                             DISPATCH()
+//                         }
+//                         PyVar* _0 = frame->f_closure_try_get(_name);
+//                         if(_0 != nullptr) {
+//                             PUSH(*_0);
+//                             DISPATCH()
+//                         }
+//                         _0 = frame->f_globals().try_get_2_likely_found(_name);
+//                         if(_0 != nullptr) {
+//                             PUSH(*_0);
+//                             DISPATCH()
+//                         }
+//                         _0 = vm->builtins->attr().try_get_2_likely_found(_name);
+//                         if(_0 != nullptr) {
+//                             PUSH(*_0);
+//                             DISPATCH()
+//                         }
+//                         vm->NameError(_name);
+//                     }
+//                         DISPATCH()
+//                     case OP_LOAD_NONLOCAL: {
+//                         StrName _name(byte.arg);
+//                         PyVar* _0 = frame->f_closure_try_get(_name);
+//                         if(_0 != nullptr) {
+//                             PUSH(*_0);
+//                             DISPATCH()
+//                         }
+//                         _0 = frame->f_globals().try_get_2_likely_found(_name);
+//                         if(_0 != nullptr) {
+//                             PUSH(*_0);
+//                             DISPATCH()
+//                         }
+//                         _0 = vm->builtins->attr().try_get_2_likely_found(_name);
+//                         if(_0 != nullptr) {
+//                             PUSH(*_0);
+//                             DISPATCH()
+//                         }
+//                         vm->NameError(_name);
+//                     }
+//                         DISPATCH()
+//                     case OP_LOAD_GLOBAL: {
+//                         StrName _name(byte.arg);
+//                         PyVar _0 = frame->f_globals().try_get_likely_found(_name);
+//                         if(_0 != nullptr) {
+//                             PUSH(_0);
+//                             DISPATCH()
+//                         }
+//                         _0 = vm->builtins->attr().try_get_likely_found(_name);
+//                         if(_0 != nullptr) {
+//                             PUSH(_0);
+//                             DISPATCH()
+//                         }
+//                         vm->NameError(_name);
+//                     }
+//                         DISPATCH()
+//                     case OP_LOAD_ATTR: {
+//                         TOP() = getattr(TOP(), StrName(byte.arg));
+//                     }
+//                         DISPATCH()
+//                     case OP_LOAD_CLASS_GLOBAL: {
+//                         assert(__curr_class != nullptr);
+//                         StrName _name(byte.arg);
+//                         PyVar _0 = getattr(__curr_class, _name, false);
+//                         if(_0 != nullptr) {
+//                             PUSH(_0);
+//                             DISPATCH()
+//                         }
+//                         // load global if attribute not found
+//                         _0 = frame->f_globals().try_get_likely_found(_name);
+//                         if(_0 != nullptr) {
+//                             PUSH(_0);
+//                             DISPATCH()
+//                         }
+//                         _0 = vm->builtins->attr().try_get_likely_found(_name);
+//                         if(_0 != nullptr) {
+//                             PUSH(_0);
+//                             DISPATCH()
+//                         }
+//                         vm->NameError(_name);
+//                     }
+//                         DISPATCH()
+//                     case OP_LOAD_METHOD: {
+//                         PyVar _0;
+//                         TOP() = get_unbound_method(TOP(), StrName(byte.arg), &_0, true, true);
+//                         PUSH(_0);
+//                     }
+//                         DISPATCH()
+//                     case OP_LOAD_SUBSCR: {
+//                         PyVar _1 = POPX();  // b
+//                         PyVar _0 = TOP();   // a
+//                         auto _ti = _tp_info(_0);
+//                         if(_ti->m__getitem__) {
+//                             TOP() = _ti->m__getitem__(this, _0, _1);
+//                         } else {
+//                             TOP() = call_method(_0, __getitem__, _1);
+//                         }
+//                     }
+//                         DISPATCH()
+//                     case OP_LOAD_SUBSCR_FAST: {
+//                         PyVar _1 = frame->_locals[byte.arg];
+//                         if(_1 == PY_NULL) vm->UnboundLocalError(c11__getitem(uint16_t, &frame->co->varnames, byte.arg));
+//                         PyVar _0 = TOP();  // a
+//                         auto _ti = _tp_info(_0);
+//                         if(_ti->m__getitem__) {
+//                             TOP() = _ti->m__getitem__(this, _0, _1);
+//                         } else {
+//                             TOP() = call_method(_0, __getitem__, _1);
+//                         }
+//                     }
+//                         DISPATCH()
+//                     case OP_LOAD_SUBSCR_SMALL_INT: {
+//                         PyVar _1 = VAR((int16_t)byte.arg);
+//                         PyVar _0 = TOP();  // a
+//                         auto _ti = _tp_info(_0);
+//                         if(_ti->m__getitem__) {
+//                             TOP() = _ti->m__getitem__(this, _0, _1);
+//                         } else {
+//                             TOP() = call_method(_0, __getitem__, _1);
+//                         }
+//                     }
+//                         DISPATCH()
+//                     case OP_STORE_FAST: frame->_locals[byte.arg] = POPX(); DISPATCH()
+//                     case OP_STORE_NAME: {
+//                         StrName _name(byte.arg);
+//                         PyVar _0 = POPX();
+//                         if(frame->_callable != nullptr) {
+//                             PyVar* slot = frame->_locals.try_get_name(_name);
+//                             if(slot != nullptr) {
+//                                 *slot = _0;  // store in locals if possible
+//                             } else {
+//                                 Function& func = frame->_callable->as<Function>();
+//                                 if(func.decl == __dynamic_func_decl) {
+//                                     assert(func._closure != nullptr);
+//                                     func._closure->set(_name, _0);
+//                                 } else {
+//                                     vm->NameError(_name);
+//                                 }
+//                             }
+//                         } else {
+//                             frame->f_globals().set(_name, _0);
+//                         }
+//                     }
+//                         DISPATCH()
+//                     case OP_STORE_GLOBAL: frame->f_globals().set(StrName(byte.arg), POPX()); DISPATCH()
+//                     case OP_STORE_ATTR: {
+//                         PyVar _0 = TOP();     // a
+//                         PyVar _1 = SECOND();  // val
+//                         setattr(_0, StrName(byte.arg), _1);
+//                         STACK_SHRINK(2);
+//                     }
+//                         DISPATCH()
+//                     case OP_STORE_SUBSCR: {
+//                         PyVar _2 = POPX();  // b
+//                         PyVar _1 = POPX();  // a
+//                         PyVar _0 = POPX();  // val
+//                         auto _ti = _tp_info(_1);
+//                         if(_ti->m__setitem__) {
+//                             _ti->m__setitem__(this, _1, _2, _0);
+//                         } else {
+//                             call_method(_1, __setitem__, _2, _0);
+//                         }
+//                     }
+//                         DISPATCH()
+//                     case OP_STORE_SUBSCR_FAST: {
+//                         PyVar _2 = frame->_locals[byte.arg];  // b
+//                         if(_2 == PY_NULL) vm->UnboundLocalError(c11__getitem(uint16_t, &frame->co->varnames, byte.arg));
+//                         PyVar _1 = POPX();  // a
+//                         PyVar _0 = POPX();  // val
+//                         auto _ti = _tp_info(_1);
+//                         if(_ti->m__setitem__) {
+//                             _ti->m__setitem__(this, _1, _2, _0);
+//                         } else {
+//                             call_method(_1, __setitem__, _2, _0);
+//                         }
+//                     }
+//                         DISPATCH()
+//                     case OP_DELETE_FAST: {
+//                         PyVar _0 = frame->_locals[byte.arg];
+//                         if(_0 == PY_NULL) vm->UnboundLocalError(c11__getitem(uint16_t, &frame->co->varnames, byte.arg));
+//                         frame->_locals[byte.arg].set_null();
+//                     }
+//                         DISPATCH()
+//                     case OP_DELETE_NAME: {
+//                         StrName _name(byte.arg);
+//                         if(frame->_callable != nullptr) {
+//                             PyVar* slot = frame->_locals.try_get_name(_name);
+//                             if(slot != nullptr) {
+//                                 slot->set_null();
+//                             } else {
+//                                 Function& func = frame->_callable->as<Function>();
+//                                 if(func.decl == __dynamic_func_decl) {
+//                                     assert(func._closure != nullptr);
+//                                     bool ok = func._closure->del(_name);
+//                                     if(!ok) vm->NameError(_name);
+//                                 } else {
+//                                     vm->NameError(_name);
+//                                 }
+//                             }
+//                         } else {
+//                             if(!frame->f_globals().del(_name)) vm->NameError(_name);
+//                         }
+//                     }
+//                         DISPATCH()
+//                     case OP_DELETE_GLOBAL: {
+//                         StrName _name(byte.arg);
+//                         if(!frame->f_globals().del(_name)) vm->NameError(_name);
+//                     }
+//                         DISPATCH()
+//                     case OP_DELETE_ATTR: {
+//                         PyVar _0 = POPX();
+//                         delattr(_0, StrName(byte.arg));
+//                     }
+//                         DISPATCH()
+//                     case OP_DELETE_SUBSCR: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = POPX();
+//                         auto _ti = _tp_info(_0);
+//                         if(_ti->m__delitem__) {
+//                             _ti->m__delitem__(this, _0, _1);
+//                         } else {
+//                             call_method(_0, __delitem__, _1);
+//                         }
+//                     }
+//                         DISPATCH()
+//                     /*****************************************/
+//                     case OP_BUILD_LONG: {
+//                         PyVar _0 = builtins->attr().try_get_likely_found(pk_id_long);
+//                         if(_0 == nullptr) AttributeError(builtins, pk_id_long);
+//                         TOP() = call(_0, TOP());
+//                     }
+//                         DISPATCH()
+//                     case OP_BUILD_IMAG: {
+//                         PyVar _0 = builtins->attr().try_get_likely_found(pk_id_complex);
+//                         if(_0 == nullptr) AttributeError(builtins, pk_id_long);
+//                         TOP() = call(_0, VAR(0), TOP());
+//                     }
+//                         DISPATCH()
+//                     case OP_BUILD_BYTES: {
+//                         const Str& s = CAST(Str&, TOP());
+//                         unsigned char* p = (unsigned char*)std::malloc(s.size);
+//                         std::memcpy(p, s.c_str(), s.size);
+//                         TOP() = VAR(Bytes(p, s.size));
+//                     }
+//                         DISPATCH()
+//                     case OP_BUILD_TUPLE: {
+//                         PyVar _0 = VAR(STACK_VIEW(byte.arg).to_tuple());
+//                         STACK_SHRINK(byte.arg);
+//                         PUSH(_0);
+//                     }
+//                         DISPATCH()
+//                     case OP_BUILD_LIST: {
+//                         PyVar _0 = VAR(STACK_VIEW(byte.arg).to_list());
+//                         STACK_SHRINK(byte.arg);
+//                         PUSH(_0);
+//                     }
+//                         DISPATCH()
+//                     case OP_BUILD_DICT: {
+//                         if(byte.arg == 0) {
+//                             PUSH(VAR(Dict()));
+//                             DISPATCH()
+//                         }
+//                         PyVar _0 = VAR(STACK_VIEW(byte.arg).to_list());
+//                         _0 = call(_t(tp_dict), _0);
+//                         STACK_SHRINK(byte.arg);
+//                         PUSH(_0);
+//                     }
+//                         DISPATCH()
+//                     case OP_BUILD_SET: {
+//                         PyVar _0 = VAR(STACK_VIEW(byte.arg).to_list());
+//                         _0 = call(builtins->attr()[pk_id_set], _0);
+//                         STACK_SHRINK(byte.arg);
+//                         PUSH(_0);
+//                     }
+//                         DISPATCH()
+//                     case OP_BUILD_SLICE: {
+//                         PyVar _2 = POPX();  // step
+//                         PyVar _1 = POPX();  // stop
+//                         PyVar _0 = POPX();  // start
+//                         PUSH(VAR(Slice(_0, _1, _2)));
+//                     }
+//                         DISPATCH()
+//                     case OP_BUILD_STRING: {
+//                         SStream ss;
+//                         ArgsView view = STACK_VIEW(byte.arg);
+//                         for(PyVar obj: view)
+//                             ss << py_str(obj);
+//                         STACK_SHRINK(byte.arg);
+//                         PUSH(VAR(ss.str()));
+//                     }
+//                         DISPATCH()
+//                     /*****************************************/
+//                     case OP_BUILD_TUPLE_UNPACK: {
+//                         List list;
+//                         __unpack_as_list(STACK_VIEW(byte.arg), list);
+//                         STACK_SHRINK(byte.arg);
+//                         PyVar _0 = VAR(list.to_tuple());
+//                         PUSH(_0);
+//                     }
+//                         DISPATCH()
+//                     case OP_BUILD_LIST_UNPACK: {
+//                         List list;
+//                         __unpack_as_list(STACK_VIEW(byte.arg), list);
+//                         STACK_SHRINK(byte.arg);
+//                         PyVar _0 = VAR(std::move(list));
+//                         PUSH(_0);
+//                     }
+//                         DISPATCH()
+//                     case OP_BUILD_DICT_UNPACK: {
+//                         Dict dict;
+//                         __unpack_as_dict(STACK_VIEW(byte.arg), dict);
+//                         STACK_SHRINK(byte.arg);
+//                         PyVar _0 = VAR(std::move(dict));
+//                         PUSH(_0);
+//                     }
+//                         DISPATCH()
+//                     case OP_BUILD_SET_UNPACK: {
+//                         List list;
+//                         __unpack_as_list(STACK_VIEW(byte.arg), list);
+//                         STACK_SHRINK(byte.arg);
+//                         PyVar _0 = VAR(std::move(list));
+//                         _0 = call(builtins->attr()[pk_id_set], _0);
+//                         PUSH(_0);
+//                     }
+//                         DISPATCH()
+//                         /*****************************************/
+// #define BINARY_OP_SPECIAL(func)                                                                                        \
+//     _ti = _tp_info(_0);                                                                                                \
+//     if(_ti->m##func) {                                                                                                 \
+//         TOP() = _ti->m##func(this, _0, _1);                                                                            \
+//     } else {                                                                                                           \
+//         PyVar self;                                                                                                    \
+//         PyVar _2 = get_unbound_method(_0, func, &self, false);                                                         \
+//         if(_2 != nullptr)                                                                                              \
+//             TOP() = call_method(self, _2, _1);                                                                         \
+//         else                                                                                                           \
+//             TOP() = NotImplemented;                                                                                    \
+//     }
 
-#define BINARY_OP_RSPECIAL(op, func)                                                                                   \
-    if(is_not_implemented(TOP())) {                                                                                    \
-        PyVar self;                                                                                                    \
-        PyVar _2 = get_unbound_method(_1, func, &self, false);                                                         \
-        if(_2 != nullptr)                                                                                              \
-            TOP() = call_method(self, _2, _0);                                                                         \
-        else                                                                                                           \
-            BinaryOptError(op, _0, _1);                                                                                \
-        if(is_not_implemented(TOP())) BinaryOptError(op, _0, _1);                                                      \
-    }
+// #define BINARY_OP_RSPECIAL(op, func)                                                                                   \
+//     if(is_not_implemented(TOP())) {                                                                                    \
+//         PyVar self;                                                                                                    \
+//         PyVar _2 = get_unbound_method(_1, func, &self, false);                                                         \
+//         if(_2 != nullptr)                                                                                              \
+//             TOP() = call_method(self, _2, _0);                                                                         \
+//         else                                                                                                           \
+//             BinaryOptError(op, _0, _1);                                                                                \
+//         if(is_not_implemented(TOP())) BinaryOptError(op, _0, _1);                                                      \
+//     }
 
-                    case OP_BINARY_TRUEDIV: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        const PyTypeInfo* _ti;
-                        BINARY_OP_SPECIAL(__truediv__);
-                        if(is_not_implemented(TOP())) BinaryOptError("/", _0, _1);
-                    }
-                        DISPATCH()
-                    case OP_BINARY_POW: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        const PyTypeInfo* _ti;
-                        BINARY_OP_SPECIAL(__pow__);
-                        if(is_not_implemented(TOP())) BinaryOptError("**", _0, _1);
-                    }
-                        DISPATCH()
-                    case OP_BINARY_ADD: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        PREDICT_INT_OP(+)
-                        const PyTypeInfo* _ti;
-                        BINARY_OP_SPECIAL(__add__);
-                        BINARY_OP_RSPECIAL("+", __radd__);
-                    }
-                        DISPATCH()
-                    case OP_BINARY_SUB: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        PREDICT_INT_OP(-)
-                        const PyTypeInfo* _ti;
-                        BINARY_OP_SPECIAL(__sub__);
-                        BINARY_OP_RSPECIAL("-", __rsub__);
-                    }
-                        DISPATCH()
-                    case OP_BINARY_MUL: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        PREDICT_INT_OP(*)
-                        const PyTypeInfo* _ti;
-                        BINARY_OP_SPECIAL(__mul__);
-                        BINARY_OP_RSPECIAL("*", __rmul__);
-                    }
-                        DISPATCH()
-                    case OP_BINARY_FLOORDIV: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        PREDICT_INT_DIV_OP(/)
-                        const PyTypeInfo* _ti;
-                        BINARY_OP_SPECIAL(__floordiv__);
-                        if(is_not_implemented(TOP())) BinaryOptError("//", _0, _1);
-                    }
-                        DISPATCH()
-                    case OP_BINARY_MOD: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        PREDICT_INT_DIV_OP(%)
-                        const PyTypeInfo* _ti;
-                        BINARY_OP_SPECIAL(__mod__);
-                        if(is_not_implemented(TOP())) BinaryOptError("%", _0, _1);
-                    }
-                        DISPATCH()
-                    case OP_COMPARE_LT: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        PREDICT_INT_OP(<)
-                        TOP() = VAR(py_lt(_0, _1));
-                    }
-                        DISPATCH()
-                    case OP_COMPARE_LE: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        PREDICT_INT_OP(<=)
-                        TOP() = VAR(py_le(_0, _1));
-                    }
-                        DISPATCH()
-                    case OP_COMPARE_EQ: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        TOP() = VAR(py_eq(_0, _1));
-                    }
-                        DISPATCH()
-                    case OP_COMPARE_NE: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        TOP() = VAR(py_ne(_0, _1));
-                    }
-                        DISPATCH()
-                    case OP_COMPARE_GT: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        PREDICT_INT_OP(>)
-                        TOP() = VAR(py_gt(_0, _1));
-                    }
-                        DISPATCH()
-                    case OP_COMPARE_GE: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        PREDICT_INT_OP(>=)
-                        TOP() = VAR(py_ge(_0, _1));
-                    }
-                        DISPATCH()
-                    case OP_BITWISE_LSHIFT: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        PREDICT_INT_OP(<<)
-                        const PyTypeInfo* _ti;
-                        BINARY_OP_SPECIAL(__lshift__);
-                        if(is_not_implemented(TOP())) BinaryOptError("<<", _0, _1);
-                    }
-                        DISPATCH()
-                    case OP_BITWISE_RSHIFT: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        PREDICT_INT_OP(>>)
-                        const PyTypeInfo* _ti;
-                        BINARY_OP_SPECIAL(__rshift__);
-                        if(is_not_implemented(TOP())) BinaryOptError(">>", _0, _1);
-                    }
-                        DISPATCH()
-                    case OP_BITWISE_AND: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        PREDICT_INT_OP(&)
-                        const PyTypeInfo* _ti;
-                        BINARY_OP_SPECIAL(__and__);
-                        if(is_not_implemented(TOP())) BinaryOptError("&", _0, _1);
-                    }
-                        DISPATCH()
-                    case OP_BITWISE_OR: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        PREDICT_INT_OP(|)
-                        const PyTypeInfo* _ti;
-                        BINARY_OP_SPECIAL(__or__);
-                        if(is_not_implemented(TOP())) BinaryOptError("|", _0, _1);
-                    }
-                        DISPATCH()
-                    case OP_BITWISE_XOR: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        PREDICT_INT_OP(^)
-                        const PyTypeInfo* _ti;
-                        BINARY_OP_SPECIAL(__xor__);
-                        if(is_not_implemented(TOP())) BinaryOptError("^", _0, _1);
-                    }
-                        DISPATCH()
-                    case OP_BINARY_MATMUL: {
-                        PyVar _1 = POPX();
-                        PyVar _0 = TOP();
-                        const PyTypeInfo* _ti;
-                        BINARY_OP_SPECIAL(__matmul__);
-                        if(is_not_implemented(TOP())) BinaryOptError("@", _0, _1);
-                    }
-                        DISPATCH()
+//                     case OP_BINARY_TRUEDIV: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         const PyTypeInfo* _ti;
+//                         BINARY_OP_SPECIAL(__truediv__);
+//                         if(is_not_implemented(TOP())) BinaryOptError("/", _0, _1);
+//                     }
+//                         DISPATCH()
+//                     case OP_BINARY_POW: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         const PyTypeInfo* _ti;
+//                         BINARY_OP_SPECIAL(__pow__);
+//                         if(is_not_implemented(TOP())) BinaryOptError("**", _0, _1);
+//                     }
+//                         DISPATCH()
+//                     case OP_BINARY_ADD: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         PREDICT_INT_OP(+)
+//                         const PyTypeInfo* _ti;
+//                         BINARY_OP_SPECIAL(__add__);
+//                         BINARY_OP_RSPECIAL("+", __radd__);
+//                     }
+//                         DISPATCH()
+//                     case OP_BINARY_SUB: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         PREDICT_INT_OP(-)
+//                         const PyTypeInfo* _ti;
+//                         BINARY_OP_SPECIAL(__sub__);
+//                         BINARY_OP_RSPECIAL("-", __rsub__);
+//                     }
+//                         DISPATCH()
+//                     case OP_BINARY_MUL: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         PREDICT_INT_OP(*)
+//                         const PyTypeInfo* _ti;
+//                         BINARY_OP_SPECIAL(__mul__);
+//                         BINARY_OP_RSPECIAL("*", __rmul__);
+//                     }
+//                         DISPATCH()
+//                     case OP_BINARY_FLOORDIV: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         PREDICT_INT_DIV_OP(/)
+//                         const PyTypeInfo* _ti;
+//                         BINARY_OP_SPECIAL(__floordiv__);
+//                         if(is_not_implemented(TOP())) BinaryOptError("//", _0, _1);
+//                     }
+//                         DISPATCH()
+//                     case OP_BINARY_MOD: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         PREDICT_INT_DIV_OP(%)
+//                         const PyTypeInfo* _ti;
+//                         BINARY_OP_SPECIAL(__mod__);
+//                         if(is_not_implemented(TOP())) BinaryOptError("%", _0, _1);
+//                     }
+//                         DISPATCH()
+//                     case OP_COMPARE_LT: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         PREDICT_INT_OP(<)
+//                         TOP() = VAR(py_lt(_0, _1));
+//                     }
+//                         DISPATCH()
+//                     case OP_COMPARE_LE: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         PREDICT_INT_OP(<=)
+//                         TOP() = VAR(py_le(_0, _1));
+//                     }
+//                         DISPATCH()
+//                     case OP_COMPARE_EQ: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         TOP() = VAR(py_eq(_0, _1));
+//                     }
+//                         DISPATCH()
+//                     case OP_COMPARE_NE: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         TOP() = VAR(py_ne(_0, _1));
+//                     }
+//                         DISPATCH()
+//                     case OP_COMPARE_GT: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         PREDICT_INT_OP(>)
+//                         TOP() = VAR(py_gt(_0, _1));
+//                     }
+//                         DISPATCH()
+//                     case OP_COMPARE_GE: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         PREDICT_INT_OP(>=)
+//                         TOP() = VAR(py_ge(_0, _1));
+//                     }
+//                         DISPATCH()
+//                     case OP_BITWISE_LSHIFT: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         PREDICT_INT_OP(<<)
+//                         const PyTypeInfo* _ti;
+//                         BINARY_OP_SPECIAL(__lshift__);
+//                         if(is_not_implemented(TOP())) BinaryOptError("<<", _0, _1);
+//                     }
+//                         DISPATCH()
+//                     case OP_BITWISE_RSHIFT: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         PREDICT_INT_OP(>>)
+//                         const PyTypeInfo* _ti;
+//                         BINARY_OP_SPECIAL(__rshift__);
+//                         if(is_not_implemented(TOP())) BinaryOptError(">>", _0, _1);
+//                     }
+//                         DISPATCH()
+//                     case OP_BITWISE_AND: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         PREDICT_INT_OP(&)
+//                         const PyTypeInfo* _ti;
+//                         BINARY_OP_SPECIAL(__and__);
+//                         if(is_not_implemented(TOP())) BinaryOptError("&", _0, _1);
+//                     }
+//                         DISPATCH()
+//                     case OP_BITWISE_OR: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         PREDICT_INT_OP(|)
+//                         const PyTypeInfo* _ti;
+//                         BINARY_OP_SPECIAL(__or__);
+//                         if(is_not_implemented(TOP())) BinaryOptError("|", _0, _1);
+//                     }
+//                         DISPATCH()
+//                     case OP_BITWISE_XOR: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         PREDICT_INT_OP(^)
+//                         const PyTypeInfo* _ti;
+//                         BINARY_OP_SPECIAL(__xor__);
+//                         if(is_not_implemented(TOP())) BinaryOptError("^", _0, _1);
+//                     }
+//                         DISPATCH()
+//                     case OP_BINARY_MATMUL: {
+//                         PyVar _1 = POPX();
+//                         PyVar _0 = TOP();
+//                         const PyTypeInfo* _ti;
+//                         BINARY_OP_SPECIAL(__matmul__);
+//                         if(is_not_implemented(TOP())) BinaryOptError("@", _0, _1);
+//                     }
+//                         DISPATCH()
 
-#undef BINARY_OP_SPECIAL
-#undef BINARY_OP_RSPECIAL
-#undef PREDICT_INT_OP
+// #undef BINARY_OP_SPECIAL
+// #undef BINARY_OP_RSPECIAL
+// #undef PREDICT_INT_OP
 
-                    case OP_IS_OP: {
-                        PyVar _1 = POPX();  // rhs
-                        PyVar _0 = TOP();   // lhs
-                        TOP() = PyVar__IS_OP(&_0, &_1) ? True : False;
-                    }
-                        DISPATCH()
-                    case OP_IS_NOT_OP: {
-                        PyVar _1 = POPX();  // rhs
-                        PyVar _0 = TOP();   // lhs
-                        TOP() = PyVar__IS_OP(&_0, &_1) ? False : True;
-                    }
-                        DISPATCH()
-                    case OP_CONTAINS_OP: {
-                        // a in b -> b __contains__ a
-                        auto _ti = _tp_info(TOP());
-                        PyVar _0;
-                        if(_ti->m__contains__) {
-                            _0 = _ti->m__contains__(this, TOP(), SECOND());
-                        } else {
-                            _0 = call_method(TOP(), __contains__, SECOND());
-                        }
-                        POP();
-                        TOP() = VAR(static_cast<bool>((int)CAST(bool, _0) ^ byte.arg));
-                    }
-                        DISPATCH()
-                    /*****************************************/
-                    case OP_JUMP_FORWARD: DISPATCH_JUMP((int16_t)byte.arg)
-                    case OP_POP_JUMP_IF_FALSE:
-                        if(!py_bool(POPX())) DISPATCH_JUMP((int16_t)byte.arg)
-                        DISPATCH()
-                    case OP_POP_JUMP_IF_TRUE:
-                        if(py_bool(POPX())) DISPATCH_JUMP((int16_t)byte.arg)
-                        DISPATCH()
-                    case OP_JUMP_IF_TRUE_OR_POP:
-                        if(py_bool(TOP())) {
-                            DISPATCH_JUMP((int16_t)byte.arg)
-                        } else {
-                            POP();
-                            DISPATCH()
-                        }
-                    case OP_JUMP_IF_FALSE_OR_POP:
-                        if(!py_bool(TOP())) {
-                            DISPATCH_JUMP((int16_t)byte.arg)
-                        } else {
-                            POP();
-                            DISPATCH()
-                        }
-                    case OP_SHORTCUT_IF_FALSE_OR_POP:
-                        if(!py_bool(TOP())) {  // [b, False]
-                            STACK_SHRINK(2);   // []
-                            PUSH(vm->False);   // [False]
-                            DISPATCH_JUMP((int16_t)byte.arg)
-                        } else {
-                            POP();  // [b]
-                            DISPATCH()
-                        }
-                    case OP_LOOP_CONTINUE:
-                        // just an alias of OP_JUMP_FORWARD
-                        DISPATCH_JUMP((int16_t)byte.arg)
-                    case OP_LOOP_BREAK: {
-                        frame->prepare_jump_break(&s_data, frame->ip() + byte.arg);
-                        DISPATCH_JUMP((int16_t)byte.arg)
-                    }
-                    case OP_JUMP_ABSOLUTE_TOP: DISPATCH_JUMP_ABSOLUTE(_CAST(int, POPX()))
-                    case OP_GOTO: {
-                        StrName _name(byte.arg);
-                        int target = c11_smallmap_n2i__get(&frame->co->labels, byte.arg, -1);
-                        if(target < 0) RuntimeError(_S("label ", _name.escape(), " not found"));
-                        frame->prepare_jump_break(&s_data, target);
-                        DISPATCH_JUMP_ABSOLUTE(target)
-                    }
-                    /*****************************************/
-                    case OP_FSTRING_EVAL: {
-                        PyVar _0 = c11__getitem(PyVar, &frame->co->consts, byte.arg);
-                        std::string_view string = CAST(Str&, _0).sv();
-                        // TODO: optimize this
-                        CodeObject* code = vm->compile(string, "<eval>", EVAL_MODE, true);
-                        _0 = vm->_exec(code, frame->_module, frame->_callable, frame->_locals);
-                        CodeObject__delete(code);
-                        PUSH(_0);
-                    }
-                        DISPATCH()
-                    case OP_REPR: TOP() = VAR(py_repr(TOP())); DISPATCH()
-                    case OP_CALL: {
-                        pk_ManagedHeap__collect_if_needed(&heap);
-                        PyVar _0 = vectorcall(byte.arg & 0xFF,         // ARGC
-                                              (byte.arg >> 8) & 0xFF,  // KWARGC
-                                              true);
-                        if(_0.type == tp_op_call) {
-                            frame = &callstack.top();
-                            goto __NEXT_FRAME;
-                        }
-                        PUSH(_0);
-                    }
-                        DISPATCH()
-                    case OP_CALL_TP: {
-                        pk_ManagedHeap__collect_if_needed(&heap);
-                        PyVar _0;
-                        PyVar _1;
-                        PyVar _2;
-                        // [callable, <self>, args: tuple, kwargs: dict | NULL]
-                        if(byte.arg) {
-                            _2 = POPX();
-                            _1 = POPX();
-                            for(PyVar obj: _CAST(Tuple&, _1))
-                                PUSH(obj);
-                            _CAST(Dict&, _2).apply([this](PyVar k, PyVar v) {
-                                PUSH(VAR(StrName(CAST(Str&, k)).index));
-                                PUSH(v);
-                            });
-                            _0 = vectorcall(_CAST(Tuple&, _1).size(),  // ARGC
-                                            _CAST(Dict&, _2).size(),   // KWARGC
-                                            true);
-                        } else {
-                            // no **kwargs
-                            _1 = POPX();
-                            for(PyVar obj: _CAST(Tuple&, _1))
-                                PUSH(obj);
-                            _0 = vectorcall(_CAST(Tuple&, _1).size(),  // ARGC
-                                            0,                         // KWARGC
-                                            true);
-                        }
-                        if(_0.type == tp_op_call) {
-                            frame = &callstack.top();
-                            goto __NEXT_FRAME;
-                        }
-                        PUSH(_0);
-                    }
-                        DISPATCH()
-                    case OP_RETURN_VALUE: {
-                        PyVar _0 = byte.arg == BC_NOARG ? POPX() : None;
-                        __pop_frame();
-                        if(frame == base_frame) {  // [ frameBase<- ]
-                            return _0;
-                        } else {
-                            frame = &callstack.top();
-                            PUSH(_0);
-                            goto __NEXT_FRAME;
-                        }
-                    }
-                        DISPATCH()
-                    case OP_YIELD_VALUE: return PY_OP_YIELD;
-                    /*****************************************/
-                    case OP_LIST_APPEND: {
-                        PyVar _0 = POPX();
-                        PK_OBJ_GET(List, SECOND()).push_back(_0);
-                    }
-                        DISPATCH()
-                    case OP_DICT_ADD: {
-                        PyVar _0 = POPX();
-                        const Tuple& t = PK_OBJ_GET(Tuple, _0);
-                        PK_OBJ_GET(Dict, SECOND()).set(this, t[0], t[1]);
-                    }
-                        DISPATCH()
-                    case OP_SET_ADD: {
-                        PyVar _0 = POPX();
-                        call_method(SECOND(), pk_id_add, _0);
-                    }
-                        DISPATCH()
-                    /*****************************************/
-                    case OP_UNARY_NEGATIVE: TOP() = py_negate(TOP()); DISPATCH()
-                    case OP_UNARY_NOT: TOP() = VAR(!py_bool(TOP())); DISPATCH()  
-                    case OP_UNARY_STAR: TOP() = VAR(StarWrapper(byte.arg, TOP())); DISPATCH()
-                    case OP_UNARY_INVERT: {
-                        PyVar _0;
-                        auto _ti = _tp_info(TOP());
-                        if(_ti->m__invert__)
-                            _0 = _ti->m__invert__(this, TOP());
-                        else
-                            _0 = call_method(TOP(), __invert__);
-                        TOP() = _0;
-                    }
-                        DISPATCH()
-                    /*****************************************/
-                    case OP_GET_ITER: TOP() = py_iter(TOP()); DISPATCH()
-                    case OP_GET_ITER_NEW: TOP() = py_iter(TOP()); DISPATCH()
-                    case OP_FOR_ITER: {
-                        PyVar _0 = py_next(TOP());
-                        if(_0 == StopIteration) {
-                            int target = frame->prepare_loop_break(&s_data);
-                            DISPATCH_JUMP_ABSOLUTE(target)
-                        } else {
-                            PUSH(_0);
-                            DISPATCH()
-                        }
-                    }
-                    case OP_FOR_ITER_STORE_FAST: {
-                        PyVar _0 = py_next(TOP());
-                        if(_0 == StopIteration) {
-                            int target = frame->prepare_loop_break(&s_data);
-                            DISPATCH_JUMP_ABSOLUTE(target)
-                        } else {
-                            frame->_locals[byte.arg] = _0;
-                            DISPATCH()
-                        }
-                    }
-                    case OP_FOR_ITER_STORE_GLOBAL: {
-                        PyVar _0 = py_next(TOP());
-                        if(_0 == StopIteration) {
-                            int target = frame->prepare_loop_break(&s_data);
-                            DISPATCH_JUMP_ABSOLUTE(target)
-                        } else {
-                            frame->f_globals().set(StrName(byte.arg), _0);
-                            DISPATCH()
-                        }
-                    }
-                    case OP_FOR_ITER_YIELD_VALUE: {
-                        PyVar _0 = py_next(TOP());
-                        if(_0 == StopIteration) {
-                            int target = frame->prepare_loop_break(&s_data);
-                            DISPATCH_JUMP_ABSOLUTE(target)
-                        } else {
-                            PUSH(_0);
-                            return PY_OP_YIELD;
-                        }
-                    }
-                    case OP_FOR_ITER_UNPACK: {
-                        PyVar _0 = TOP();
-                        const PyTypeInfo* _ti = _tp_info(_0);
-                        if(_ti->op__next__) {
-                            unsigned n = _ti->op__next__(this, _0);
-                            if(n == 0) {
-                                // StopIteration
-                                int target = frame->prepare_loop_break(&s_data);
-                                DISPATCH_JUMP_ABSOLUTE(target)
-                            } else if(n == 1) {
-                                // UNPACK_SEQUENCE
-                                __op_unpack_sequence(byte.arg);
-                            } else {
-                                if(n != byte.arg) {
-                                    ValueError(_S("expected ", (int)byte.arg, " values to unpack, got ", (int)n));
-                                }
-                            }
-                        } else {
-                            // FOR_ITER
-                            _0 = call_method(_0, __next__);
-                            if(_0 != StopIteration) {
-                                PUSH(_0);
-                                // UNPACK_SEQUENCE
-                                __op_unpack_sequence(byte.arg);
-                            } else {
-                                int target = frame->prepare_loop_break(&s_data);
-                                DISPATCH_JUMP_ABSOLUTE(target)
-                            }
-                        }
-                    }
-                        DISPATCH()
-                    /*****************************************/
-                    case OP_IMPORT_PATH: {
-                        PyVar _0 = c11__getitem(PyVar, &frame->co->consts, byte.arg);
-                        PUSH(py_import(CAST(Str&, _0)));
-                    }
-                        DISPATCH()
-                    case OP_POP_IMPORT_STAR: {
-                        PyVar _0 = POPX();  // pop the module
-                        PyVar _1 = _0->attr().try_get(__all__);
-                        StrName _name;
-                        if(_1 != nullptr) {
-                            for(PyVar key: CAST(List&, _1)) {
-                                _name = StrName::get(CAST(Str&, key).sv());
-                                PyVar value = _0->attr().try_get_likely_found(_name);
-                                if(value == nullptr) {
-                                    ImportError(_S("cannot import name ", _name.escape()));
-                                } else {
-                                    frame->f_globals().set(_name, value);
-                                }
-                            }
-                        } else {
-                            for(auto& [name, value]: _0->attr().items()) {
-                                std::string_view s = name.sv();
-                                if(s.empty() || s[0] == '_') continue;
-                                frame->f_globals().set(name, value);
-                            }
-                        }
-                    }
-                        DISPATCH()
-                    /*****************************************/
-                    case OP_UNPACK_SEQUENCE: {
-                        __op_unpack_sequence(byte.arg);
-                    }
-                        DISPATCH()
-                    case OP_UNPACK_EX: {
-                        auto _lock = gc_scope_lock();  // lock the gc via RAII!!
-                        PyVar _0 = py_iter(POPX());
-                        const PyTypeInfo* _ti = _tp_info(_0);
-                        PyVar _1;
-                        for(int i = 0; i < byte.arg; i++) {
-                            _1 = _py_next(_ti, _0);
-                            if(_1 == StopIteration) ValueError("not enough values to unpack");
-                            PUSH(_1);
-                        }
-                        List extras;
-                        while(true) {
-                            _1 = _py_next(_ti, _0);
-                            if(_1 == StopIteration) break;
-                            extras.push_back(_1);
-                        }
-                        PUSH(VAR(std::move(extras)));
-                    }
-                        DISPATCH()
-                    /*****************************************/
-                    case OP_BEGIN_CLASS: {
-                        StrName _name(byte.arg);
-                        PyVar _0 = POPX();  // super
-                        if(is_none(_0)) _0 = _t(tp_object);
-                        check_type(_0, tp_type);
-                        __curr_class = new_type_object(frame->_module, _name, PK_OBJ_GET(Type, _0), true);
-                    }
-                        DISPATCH()
-                    case OP_END_CLASS: {
-                        assert(__curr_class != nullptr);
-                        StrName _name(byte.arg);
-                        frame->_module->attr().set(_name, __curr_class);
-                        // call on_end_subclass
-                        PyTypeInfo* ti = &_all_types[__curr_class->as<Type>()];
-                        if(ti->base != tp_object) {
-                            PyTypeInfo* base_ti = &_all_types[ti->base];
-                            if(base_ti->on_end_subclass) base_ti->on_end_subclass(this, ti);
-                        }
-                        __curr_class = nullptr;
-                    }
-                        DISPATCH()
-                    case OP_STORE_CLASS_ATTR: {
-                        assert(__curr_class != nullptr);
-                        StrName _name(byte.arg);
-                        PyVar _0 = POPX();
-                        if(is_type(_0, tp_function)) { PK_OBJ_GET(Function, _0)._class = __curr_class; }
-                        __curr_class->attr().set(_name, _0);
-                    }
-                        DISPATCH()
-                    case OP_BEGIN_CLASS_DECORATION: {
-                        PUSH(__curr_class);
-                    }
-                        DISPATCH()
-                    case OP_END_CLASS_DECORATION: {
-                        __curr_class = POPX().get();
-                    }
-                        DISPATCH()
-                    case OP_ADD_CLASS_ANNOTATION: {
-                        assert(__curr_class != nullptr);
-                        StrName _name(byte.arg);
-                        Type type = __curr_class->as<Type>();
-                        _all_types[type].annotated_fields.push_back(_name);
-                    }
-                        DISPATCH()
-                    /*****************************************/
-                    case OP_WITH_ENTER: PUSH(call_method(TOP(), __enter__)); DISPATCH()
-                    case OP_WITH_EXIT:
-                        call_method(TOP(), __exit__);
-                        POP();
-                        DISPATCH()
-                    /*****************************************/
-                    case OP_TRY_ENTER: {
-                        frame->set_unwind_target(s_data.sp);
-                        DISPATCH()
-                    }
-                    case OP_EXCEPTION_MATCH: {
-                        PyVar assumed_type = POPX();
-                        check_type(assumed_type, tp_type);
-                        PyVar e_obj = TOP();
-                        bool ok = isinstance(e_obj, PK_OBJ_GET(Type, assumed_type));
-                        PUSH(VAR(ok));
-                    }
-                        DISPATCH()
-                    case OP_RAISE: {
-                        if(is_type(TOP(), tp_type)) { TOP() = call(TOP()); }
-                        if(!isinstance(TOP(), tp_exception)) { TypeError("exceptions must derive from Exception"); }
-                        _error(POPX());
-                    }
-                        DISPATCH()
-                    case OP_RAISE_ASSERT:
-                        if(byte.arg) {
-                            Str msg = py_str(TOP());
-                            POP();
-                            AssertionError(msg);
-                        } else {
-                            AssertionError();
-                        }
-                        DISPATCH()
-                    case OP_RE_RAISE: __raise_exc(true); DISPATCH()
-                    case OP_POP_EXCEPTION: __last_exception = POPX().get(); DISPATCH()
-                    /*****************************************/
-                    case OP_FORMAT_STRING: {
-                        PyVar _0 = POPX();
-                        const Str& spec = CAST(Str&, c11__getitem(PyVar, &frame->co->consts, byte.arg));
-                        PUSH(__format_object(_0, spec));
-                    }
-                        DISPATCH()
-                    /*****************************************/
-                    default: PK_UNREACHABLE()
-                }
-            }
-            /**********************************************************************/
-            PK_UNREACHABLE()
-        } catch(InternalException internal) {
-            __internal_exception = internal;
-            if(internal.type == InternalExceptionType::Unhandled) {
-                __last_exception = POPX().get();
-                Exception& _e = __last_exception->as<Exception>();
-                bool is_base_frame_to_be_popped = frame == base_frame;
-                __pop_frame();
-                if(callstack.empty()) {
-                    // propagate to the top level
-                    throw TopLevelException(this, &_e);
-                }
-                frame = &callstack.top();
-                PUSH(__last_exception);
-                if(is_base_frame_to_be_popped) { throw InternalException(InternalExceptionType::ToBeRaised); }
-            }
-        }
-    }
-}
+//                     case OP_IS_OP: {
+//                         PyVar _1 = POPX();  // rhs
+//                         PyVar _0 = TOP();   // lhs
+//                         TOP() = PyVar__IS_OP(&_0, &_1) ? True : False;
+//                     }
+//                         DISPATCH()
+//                     case OP_IS_NOT_OP: {
+//                         PyVar _1 = POPX();  // rhs
+//                         PyVar _0 = TOP();   // lhs
+//                         TOP() = PyVar__IS_OP(&_0, &_1) ? False : True;
+//                     }
+//                         DISPATCH()
+//                     case OP_CONTAINS_OP: {
+//                         // a in b -> b __contains__ a
+//                         auto _ti = _tp_info(TOP());
+//                         PyVar _0;
+//                         if(_ti->m__contains__) {
+//                             _0 = _ti->m__contains__(this, TOP(), SECOND());
+//                         } else {
+//                             _0 = call_method(TOP(), __contains__, SECOND());
+//                         }
+//                         POP();
+//                         TOP() = VAR(static_cast<bool>((int)CAST(bool, _0) ^ byte.arg));
+//                     }
+//                         DISPATCH()
+//                     /*****************************************/
+//                     case OP_JUMP_FORWARD: DISPATCH_JUMP((int16_t)byte.arg)
+//                     case OP_POP_JUMP_IF_FALSE:
+//                         if(!py_bool(POPX())) DISPATCH_JUMP((int16_t)byte.arg)
+//                         DISPATCH()
+//                     case OP_POP_JUMP_IF_TRUE:
+//                         if(py_bool(POPX())) DISPATCH_JUMP((int16_t)byte.arg)
+//                         DISPATCH()
+//                     case OP_JUMP_IF_TRUE_OR_POP:
+//                         if(py_bool(TOP())) {
+//                             DISPATCH_JUMP((int16_t)byte.arg)
+//                         } else {
+//                             POP();
+//                             DISPATCH()
+//                         }
+//                     case OP_JUMP_IF_FALSE_OR_POP:
+//                         if(!py_bool(TOP())) {
+//                             DISPATCH_JUMP((int16_t)byte.arg)
+//                         } else {
+//                             POP();
+//                             DISPATCH()
+//                         }
+//                     case OP_SHORTCUT_IF_FALSE_OR_POP:
+//                         if(!py_bool(TOP())) {  // [b, False]
+//                             STACK_SHRINK(2);   // []
+//                             PUSH(vm->False);   // [False]
+//                             DISPATCH_JUMP((int16_t)byte.arg)
+//                         } else {
+//                             POP();  // [b]
+//                             DISPATCH()
+//                         }
+//                     case OP_LOOP_CONTINUE:
+//                         // just an alias of OP_JUMP_FORWARD
+//                         DISPATCH_JUMP((int16_t)byte.arg)
+//                     case OP_LOOP_BREAK: {
+//                         frame->prepare_jump_break(&s_data, frame->ip() + byte.arg);
+//                         DISPATCH_JUMP((int16_t)byte.arg)
+//                     }
+//                     case OP_JUMP_ABSOLUTE_TOP: DISPATCH_JUMP_ABSOLUTE(_CAST(int, POPX()))
+//                     case OP_GOTO: {
+//                         StrName _name(byte.arg);
+//                         int target = c11_smallmap_n2i__get(&frame->co->labels, byte.arg, -1);
+//                         if(target < 0) RuntimeError(_S("label ", _name.escape(), " not found"));
+//                         frame->prepare_jump_break(&s_data, target);
+//                         DISPATCH_JUMP_ABSOLUTE(target)
+//                     }
+//                     /*****************************************/
+//                     case OP_FSTRING_EVAL: {
+//                         PyVar _0 = c11__getitem(PyVar, &frame->co->consts, byte.arg);
+//                         std::string_view string = CAST(Str&, _0).sv();
+//                         // TODO: optimize this
+//                         CodeObject* code = vm->compile(string, "<eval>", EVAL_MODE, true);
+//                         _0 = vm->_exec(code, frame->_module, frame->_callable, frame->_locals);
+//                         CodeObject__delete(code);
+//                         PUSH(_0);
+//                     }
+//                         DISPATCH()
+//                     case OP_REPR: TOP() = VAR(py_repr(TOP())); DISPATCH()
+//                     case OP_CALL: {
+//                         pk_ManagedHeap__collect_if_needed(&heap);
+//                         PyVar _0 = vectorcall(byte.arg & 0xFF,         // ARGC
+//                                               (byte.arg >> 8) & 0xFF,  // KWARGC
+//                                               true);
+//                         if(_0.type == tp_op_call) {
+//                             frame = &callstack.top();
+//                             goto __NEXT_FRAME;
+//                         }
+//                         PUSH(_0);
+//                     }
+//                         DISPATCH()
+//                     case OP_CALL_TP: {
+//                         pk_ManagedHeap__collect_if_needed(&heap);
+//                         PyVar _0;
+//                         PyVar _1;
+//                         PyVar _2;
+//                         // [callable, <self>, args: tuple, kwargs: dict | NULL]
+//                         if(byte.arg) {
+//                             _2 = POPX();
+//                             _1 = POPX();
+//                             for(PyVar obj: _CAST(Tuple&, _1))
+//                                 PUSH(obj);
+//                             _CAST(Dict&, _2).apply([this](PyVar k, PyVar v) {
+//                                 PUSH(VAR(StrName(CAST(Str&, k)).index));
+//                                 PUSH(v);
+//                             });
+//                             _0 = vectorcall(_CAST(Tuple&, _1).size(),  // ARGC
+//                                             _CAST(Dict&, _2).size(),   // KWARGC
+//                                             true);
+//                         } else {
+//                             // no **kwargs
+//                             _1 = POPX();
+//                             for(PyVar obj: _CAST(Tuple&, _1))
+//                                 PUSH(obj);
+//                             _0 = vectorcall(_CAST(Tuple&, _1).size(),  // ARGC
+//                                             0,                         // KWARGC
+//                                             true);
+//                         }
+//                         if(_0.type == tp_op_call) {
+//                             frame = &callstack.top();
+//                             goto __NEXT_FRAME;
+//                         }
+//                         PUSH(_0);
+//                     }
+//                         DISPATCH()
+//                     case OP_RETURN_VALUE: {
+//                         PyVar _0 = byte.arg == BC_NOARG ? POPX() : None;
+//                         __pop_frame();
+//                         if(frame == base_frame) {  // [ frameBase<- ]
+//                             return _0;
+//                         } else {
+//                             frame = &callstack.top();
+//                             PUSH(_0);
+//                             goto __NEXT_FRAME;
+//                         }
+//                     }
+//                         DISPATCH()
+//                     case OP_YIELD_VALUE: return PY_OP_YIELD;
+//                     /*****************************************/
+//                     case OP_LIST_APPEND: {
+//                         PyVar _0 = POPX();
+//                         PK_OBJ_GET(List, SECOND()).push_back(_0);
+//                     }
+//                         DISPATCH()
+//                     case OP_DICT_ADD: {
+//                         PyVar _0 = POPX();
+//                         const Tuple& t = PK_OBJ_GET(Tuple, _0);
+//                         PK_OBJ_GET(Dict, SECOND()).set(this, t[0], t[1]);
+//                     }
+//                         DISPATCH()
+//                     case OP_SET_ADD: {
+//                         PyVar _0 = POPX();
+//                         call_method(SECOND(), pk_id_add, _0);
+//                     }
+//                         DISPATCH()
+//                     /*****************************************/
+//                     case OP_UNARY_NEGATIVE: TOP() = py_negate(TOP()); DISPATCH()
+//                     case OP_UNARY_NOT: TOP() = VAR(!py_bool(TOP())); DISPATCH()  
+//                     case OP_UNARY_STAR: TOP() = VAR(StarWrapper(byte.arg, TOP())); DISPATCH()
+//                     case OP_UNARY_INVERT: {
+//                         PyVar _0;
+//                         auto _ti = _tp_info(TOP());
+//                         if(_ti->m__invert__)
+//                             _0 = _ti->m__invert__(this, TOP());
+//                         else
+//                             _0 = call_method(TOP(), __invert__);
+//                         TOP() = _0;
+//                     }
+//                         DISPATCH()
+//                     /*****************************************/
+//                     case OP_GET_ITER: TOP() = py_iter(TOP()); DISPATCH()
+//                     case OP_GET_ITER_NEW: TOP() = py_iter(TOP()); DISPATCH()
+//                     case OP_FOR_ITER: {
+//                         PyVar _0 = py_next(TOP());
+//                         if(_0 == StopIteration) {
+//                             int target = frame->prepare_loop_break(&s_data);
+//                             DISPATCH_JUMP_ABSOLUTE(target)
+//                         } else {
+//                             PUSH(_0);
+//                             DISPATCH()
+//                         }
+//                     }
+//                     case OP_FOR_ITER_STORE_FAST: {
+//                         PyVar _0 = py_next(TOP());
+//                         if(_0 == StopIteration) {
+//                             int target = frame->prepare_loop_break(&s_data);
+//                             DISPATCH_JUMP_ABSOLUTE(target)
+//                         } else {
+//                             frame->_locals[byte.arg] = _0;
+//                             DISPATCH()
+//                         }
+//                     }
+//                     case OP_FOR_ITER_STORE_GLOBAL: {
+//                         PyVar _0 = py_next(TOP());
+//                         if(_0 == StopIteration) {
+//                             int target = frame->prepare_loop_break(&s_data);
+//                             DISPATCH_JUMP_ABSOLUTE(target)
+//                         } else {
+//                             frame->f_globals().set(StrName(byte.arg), _0);
+//                             DISPATCH()
+//                         }
+//                     }
+//                     case OP_FOR_ITER_YIELD_VALUE: {
+//                         PyVar _0 = py_next(TOP());
+//                         if(_0 == StopIteration) {
+//                             int target = frame->prepare_loop_break(&s_data);
+//                             DISPATCH_JUMP_ABSOLUTE(target)
+//                         } else {
+//                             PUSH(_0);
+//                             return PY_OP_YIELD;
+//                         }
+//                     }
+//                     case OP_FOR_ITER_UNPACK: {
+//                         PyVar _0 = TOP();
+//                         const PyTypeInfo* _ti = _tp_info(_0);
+//                         if(_ti->op__next__) {
+//                             unsigned n = _ti->op__next__(this, _0);
+//                             if(n == 0) {
+//                                 // StopIteration
+//                                 int target = frame->prepare_loop_break(&s_data);
+//                                 DISPATCH_JUMP_ABSOLUTE(target)
+//                             } else if(n == 1) {
+//                                 // UNPACK_SEQUENCE
+//                                 __op_unpack_sequence(byte.arg);
+//                             } else {
+//                                 if(n != byte.arg) {
+//                                     ValueError(_S("expected ", (int)byte.arg, " values to unpack, got ", (int)n));
+//                                 }
+//                             }
+//                         } else {
+//                             // FOR_ITER
+//                             _0 = call_method(_0, __next__);
+//                             if(_0 != StopIteration) {
+//                                 PUSH(_0);
+//                                 // UNPACK_SEQUENCE
+//                                 __op_unpack_sequence(byte.arg);
+//                             } else {
+//                                 int target = frame->prepare_loop_break(&s_data);
+//                                 DISPATCH_JUMP_ABSOLUTE(target)
+//                             }
+//                         }
+//                     }
+//                         DISPATCH()
+//                     /*****************************************/
+//                     case OP_IMPORT_PATH: {
+//                         PyVar _0 = c11__getitem(PyVar, &frame->co->consts, byte.arg);
+//                         PUSH(py_import(CAST(Str&, _0)));
+//                     }
+//                         DISPATCH()
+//                     case OP_POP_IMPORT_STAR: {
+//                         PyVar _0 = POPX();  // pop the module
+//                         PyVar _1 = _0->attr().try_get(__all__);
+//                         StrName _name;
+//                         if(_1 != nullptr) {
+//                             for(PyVar key: CAST(List&, _1)) {
+//                                 _name = StrName::get(CAST(Str&, key).sv());
+//                                 PyVar value = _0->attr().try_get_likely_found(_name);
+//                                 if(value == nullptr) {
+//                                     ImportError(_S("cannot import name ", _name.escape()));
+//                                 } else {
+//                                     frame->f_globals().set(_name, value);
+//                                 }
+//                             }
+//                         } else {
+//                             for(auto& [name, value]: _0->attr().items()) {
+//                                 std::string_view s = name.sv();
+//                                 if(s.empty() || s[0] == '_') continue;
+//                                 frame->f_globals().set(name, value);
+//                             }
+//                         }
+//                     }
+//                         DISPATCH()
+//                     /*****************************************/
+//                     case OP_UNPACK_SEQUENCE: {
+//                         __op_unpack_sequence(byte.arg);
+//                     }
+//                         DISPATCH()
+//                     case OP_UNPACK_EX: {
+//                         auto _lock = gc_scope_lock();  // lock the gc via RAII!!
+//                         PyVar _0 = py_iter(POPX());
+//                         const PyTypeInfo* _ti = _tp_info(_0);
+//                         PyVar _1;
+//                         for(int i = 0; i < byte.arg; i++) {
+//                             _1 = _py_next(_ti, _0);
+//                             if(_1 == StopIteration) ValueError("not enough values to unpack");
+//                             PUSH(_1);
+//                         }
+//                         List extras;
+//                         while(true) {
+//                             _1 = _py_next(_ti, _0);
+//                             if(_1 == StopIteration) break;
+//                             extras.push_back(_1);
+//                         }
+//                         PUSH(VAR(std::move(extras)));
+//                     }
+//                         DISPATCH()
+//                     /*****************************************/
+//                     case OP_BEGIN_CLASS: {
+//                         StrName _name(byte.arg);
+//                         PyVar _0 = POPX();  // super
+//                         if(is_none(_0)) _0 = _t(tp_object);
+//                         check_type(_0, tp_type);
+//                         __curr_class = new_type_object(frame->_module, _name, PK_OBJ_GET(Type, _0), true);
+//                     }
+//                         DISPATCH()
+//                     case OP_END_CLASS: {
+//                         assert(__curr_class != nullptr);
+//                         StrName _name(byte.arg);
+//                         frame->_module->attr().set(_name, __curr_class);
+//                         // call on_end_subclass
+//                         PyTypeInfo* ti = &_all_types[__curr_class->as<Type>()];
+//                         if(ti->base != tp_object) {
+//                             PyTypeInfo* base_ti = &_all_types[ti->base];
+//                             if(base_ti->on_end_subclass) base_ti->on_end_subclass(this, ti);
+//                         }
+//                         __curr_class = nullptr;
+//                     }
+//                         DISPATCH()
+//                     case OP_STORE_CLASS_ATTR: {
+//                         assert(__curr_class != nullptr);
+//                         StrName _name(byte.arg);
+//                         PyVar _0 = POPX();
+//                         if(is_type(_0, tp_function)) { PK_OBJ_GET(Function, _0)._class = __curr_class; }
+//                         __curr_class->attr().set(_name, _0);
+//                     }
+//                         DISPATCH()
+//                     case OP_BEGIN_CLASS_DECORATION: {
+//                         PUSH(__curr_class);
+//                     }
+//                         DISPATCH()
+//                     case OP_END_CLASS_DECORATION: {
+//                         __curr_class = POPX().get();
+//                     }
+//                         DISPATCH()
+//                     case OP_ADD_CLASS_ANNOTATION: {
+//                         assert(__curr_class != nullptr);
+//                         StrName _name(byte.arg);
+//                         Type type = __curr_class->as<Type>();
+//                         _all_types[type].annotated_fields.push_back(_name);
+//                     }
+//                         DISPATCH()
+//                     /*****************************************/
+//                     case OP_WITH_ENTER: PUSH(call_method(TOP(), __enter__)); DISPATCH()
+//                     case OP_WITH_EXIT:
+//                         call_method(TOP(), __exit__);
+//                         POP();
+//                         DISPATCH()
+//                     /*****************************************/
+//                     case OP_TRY_ENTER: {
+//                         frame->set_unwind_target(s_data.sp);
+//                         DISPATCH()
+//                     }
+//                     case OP_EXCEPTION_MATCH: {
+//                         PyVar assumed_type = POPX();
+//                         check_type(assumed_type, tp_type);
+//                         PyVar e_obj = TOP();
+//                         bool ok = isinstance(e_obj, PK_OBJ_GET(Type, assumed_type));
+//                         PUSH(VAR(ok));
+//                     }
+//                         DISPATCH()
+//                     case OP_RAISE: {
+//                         if(is_type(TOP(), tp_type)) { TOP() = call(TOP()); }
+//                         if(!isinstance(TOP(), tp_exception)) { TypeError("exceptions must derive from Exception"); }
+//                         _error(POPX());
+//                     }
+//                         DISPATCH()
+//                     case OP_RAISE_ASSERT:
+//                         if(byte.arg) {
+//                             Str msg = py_str(TOP());
+//                             POP();
+//                             AssertionError(msg);
+//                         } else {
+//                             AssertionError();
+//                         }
+//                         DISPATCH()
+//                     case OP_RE_RAISE: __raise_exc(true); DISPATCH()
+//                     case OP_POP_EXCEPTION: __last_exception = POPX().get(); DISPATCH()
+//                     /*****************************************/
+//                     case OP_FORMAT_STRING: {
+//                         PyVar _0 = POPX();
+//                         const Str& spec = CAST(Str&, c11__getitem(PyVar, &frame->co->consts, byte.arg));
+//                         PUSH(__format_object(_0, spec));
+//                     }
+//                         DISPATCH()
+//                     /*****************************************/
+//                     default: PK_UNREACHABLE()
+//                 }
+//             }
+//             /**********************************************************************/
+//             PK_UNREACHABLE()
+//         } catch(InternalException internal) {
+//             __internal_exception = internal;
+//             if(internal.type == InternalExceptionType::Unhandled) {
+//                 __last_exception = POPX().get();
+//                 Exception& _e = __last_exception->as<Exception>();
+//                 bool is_base_frame_to_be_popped = frame == base_frame;
+//                 __pop_frame();
+//                 if(callstack.empty()) {
+//                     // propagate to the top level
+//                     throw TopLevelException(this, &_e);
+//                 }
+//                 frame = &callstack.top();
+//                 PUSH(__last_exception);
+//                 if(is_base_frame_to_be_popped) { throw InternalException(InternalExceptionType::ToBeRaised); }
+//             }
+//         }
+//     }
+// }
 
-#undef TOP
-#undef SECOND
-#undef THIRD
-#undef STACK_SHRINK
-#undef PUSH
-#undef POP
-#undef POPX
-#undef STACK_VIEW
+// #undef TOP
+// #undef SECOND
+// #undef THIRD
+// #undef STACK_SHRINK
+// #undef PUSH
+// #undef POP
+// #undef POPX
+// #undef STACK_VIEW
 
-#undef DISPATCH
-#undef DISPATCH_JUMP
-#undef CEVAL_STEP_CALLBACK
+// #undef DISPATCH
+// #undef DISPATCH_JUMP
+// #undef CEVAL_STEP_CALLBACK
 
-}  // namespace pkpy
+// }  // namespace pkpy

+ 1 - 1
src/interpreter/frame.c

@@ -40,7 +40,7 @@ void UnwindTarget__delete(UnwindTarget* self){
 }
 
 Frame* Frame__new(Frame* f_back, const CodeObject* co, PyObject* module_, PyObject* function, PyVar* p0, PyVar* locals, const CodeObject* locals_co){
-    static_assert(sizeof(Frame) <= kPoolFrameBlockSize);
+    static_assert(sizeof(Frame) <= kPoolFrameBlockSize, "!(sizeof(Frame) <= kPoolFrameBlockSize)");
     Frame* self = PoolFrame_alloc();
     self->f_back = f_back;
     self->ip = (Bytecode*)co->codes.data - 1;

+ 3 - 1
src/interpreter/vm.c

@@ -6,10 +6,12 @@ static unsigned char* pk_default_import_file(pk_VM* vm, const char* path){
 
 static void pk_default_stdout(pk_VM* vm, const char* s){
     fprintf(stdout, "%s", s);
+    fflush(stdout);
 }
 
 static void pk_default_stderr(pk_VM* vm, const char* s){
     fprintf(stderr, "%s", s);
+    fflush(stderr);
 }
 
 void pk_TypeInfo__ctor(pk_TypeInfo *self, StrName name, Type base, PyObject* obj, PyObject* module, bool subclass_enabled){
@@ -70,7 +72,7 @@ void pk_VM__ctor(pk_VM* self){
 
     /* Init Builtin Types */
     // 0: unused
-    pk_TypeInfo__ctor(c11_vector__emplace(&self->types), 0, 0, NULL, NULL);
+    pk_TypeInfo__ctor(c11_vector__emplace(&self->types), 0, 0, NULL, NULL, false);
     #define validate(t, expr) if(t != (expr)) abort()
 
     validate(tp_object, pk_VM__new_type(self, "object", 0, NULL, true));

+ 0 - 1
src/objects/dict.c

@@ -3,7 +3,6 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <string.h>
-#include "pocketpy/objects/public.h"
 
 #define DICT_MAX_LOAD 0.75
 #define DICT_HASH_NEXT(h) ((h) * 5 + 1)