blueloveTH 1 год назад
Родитель
Сommit
529c23043c
10 измененных файлов с 104 добавлено и 79 удалено
  1. 12 10
      .github/workflows/main.yml
  2. 3 3
      include/pocketpy/any.h
  3. 38 11
      include/pocketpy/common.h
  4. 1 1
      include/pocketpy/str.h
  5. 6 10
      include/pocketpy/vm.h
  6. 3 3
      src/ceval.cpp
  7. 4 4
      src/dataclasses.cpp
  8. 7 7
      src/pocketpy.cpp
  9. 3 3
      src/str.cpp
  10. 27 27
      src/vm.cpp

+ 12 - 10
.github/workflows/main.yml

@@ -1,15 +1,17 @@
 name: build
 name: build
 on:
 on:
-   push:
-     paths-ignore:
-       - 'docs/**'
-       - 'web/**'
-       - '**.md'
-   pull_request:
-     paths-ignore:
-       - 'docs/**'
-       - 'web/**'
-       - '**.md'
+  push:
+    branches: [ main ]
+    paths-ignore:
+      - 'docs/**'
+      - 'web/**'
+      - '**.md'
+  pull_request:
+    branches: [ main ]
+    paths-ignore:
+      - 'docs/**'
+      - 'web/**'
+      - '**.md'
 jobs:
 jobs:
   build_win32_amalgamated:
   build_win32_amalgamated:
     runs-on: windows-latest
     runs-on: windows-latest

+ 3 - 3
include/pocketpy/any.h

@@ -28,7 +28,7 @@ struct any{
 
 
     any() : data(nullptr), _vt(nullptr) {}
     any() : data(nullptr), _vt(nullptr) {}
 
 
-    operator bool() const { return _vt != nullptr; }
+    explicit operator bool() const { return _vt != nullptr; }
 
 
     template<typename T>
     template<typename T>
     any(T&& value){
     any(T&& value){
@@ -85,7 +85,7 @@ struct function<Ret(Params...)>{
 
 
     function(): _impl(), _wrapper(nullptr) {}
     function(): _impl(), _wrapper(nullptr) {}
 
 
-    operator bool() const { return _wrapper != nullptr; }
+    explicit operator bool() const { return _wrapper != nullptr; }
 
 
     template<typename F>
     template<typename F>
     function(F&& f) : _impl(std::forward<F>(f)){
     function(F&& f) : _impl(std::forward<F>(f)){
@@ -110,7 +110,7 @@ struct lightfunction<Ret(Params...)>{
 
 
     lightfunction() : _impl(nullptr), _wrapper(nullptr) {}
     lightfunction() : _impl(nullptr), _wrapper(nullptr) {}
 
 
-    operator bool() const { return _wrapper != nullptr; }
+    explicit operator bool() const { return _wrapper != nullptr; }
 
 
     template<typename F>
     template<typename F>
     lightfunction(const F& f){
     lightfunction(const F& f){

+ 38 - 11
include/pocketpy/common.h

@@ -102,7 +102,7 @@ struct Type {
 	explicit constexpr Type(int index): index(index) {}
 	explicit constexpr Type(int index): index(index) {}
 	bool operator==(Type other) const { return this->index == other.index; }
 	bool operator==(Type other) const { return this->index == other.index; }
 	bool operator!=(Type other) const { return this->index != other.index; }
 	bool operator!=(Type other) const { return this->index != other.index; }
-	operator int() const { return this->index; }
+    explicit operator bool() const { return index != -1; }
 };
 };
 
 
 #define PK_LAMBDA(x) ([](VM* vm, ArgsView args) { return x; })
 #define PK_LAMBDA(x) ([](VM* vm, ArgsView args) { return x; })
@@ -177,19 +177,27 @@ struct PyVar final{
     uint8_t flags;
     uint8_t flags;
     char _bytes[12];
     char _bytes[12];
 
 
-    PyVar(): type(), is_sso(false), flags(0) { }
-    PyVar(std::nullptr_t): type(), is_sso(false), flags(0) { }
-    PyVar(Type type, bool is_sso): type(type), is_sso(is_sso), flags(0) { }
-    PyVar(Type type, PyObject* p): type(type), is_sso(false), flags(0) { as<PyObject*>() = p; }
+    // uninitialized
+    PyVar(): type() { }
+    // zero initialized
+    PyVar(std::nullptr_t): type(), is_sso(false), flags(0), _bytes{0} { }
+    // PyObject* initialized (is_sso = false)
+    PyVar(Type type, PyObject* p): type(type), is_sso(false), flags(0) {
+        as<PyObject*>() = p;
+    }
+    // SSO initialized (is_sso = true)
+    template<typename T>
+    PyVar(Type type, T value): type(type), is_sso(true), flags(0) {
+        as<T>() = value;
+    }
 
 
     template<typename T>
     template<typename T>
     T& as() const {
     T& as() const {
         static_assert(!std::is_reference_v<T>);
         static_assert(!std::is_reference_v<T>);
-        PK_DEBUG_ASSERT(is_sso)
         return *(T*)_bytes;
         return *(T*)_bytes;
     }
     }
 
 
-    operator bool() const { return type; }
+    explicit operator bool() const { return (bool)type; }
 
 
     bool operator==(const PyVar& other) const {
     bool operator==(const PyVar& other) const {
         return memcmp(this, &other, sizeof(PyVar)) == 0;
         return memcmp(this, &other, sizeof(PyVar)) == 0;
@@ -199,14 +207,33 @@ struct PyVar final{
         return memcmp(this, &other, sizeof(PyVar)) != 0;
         return memcmp(this, &other, sizeof(PyVar)) != 0;
     }
     }
 
 
-    bool operator==(std::nullptr_t) const { return !type; }
-    bool operator!=(std::nullptr_t) const { return type; }
+    bool operator==(std::nullptr_t) const { return !(bool)type; }
+    bool operator!=(std::nullptr_t) const { return (bool)type; }
+
+    PyObject* get() const {
+        PK_DEBUG_ASSERT(!is_sso)
+        return as<PyObject*>();
+    }
+
+    PyObject* operator->() const {
+        PK_DEBUG_ASSERT(!is_sso)
+        return as<PyObject*>();
+    }
 
 
-    PyObject* get() const { return as<PyObject*>(); }
     i64 hash() const { return as<i64>(); }
     i64 hash() const { return as<i64>(); }
-    PyObject* operator->() const { return as<PyObject*>(); }
 };
 };
 
 
 static_assert(sizeof(PyVar) == 16 && is_pod_v<PyVar>);
 static_assert(sizeof(PyVar) == 16 && is_pod_v<PyVar>);
 
 
 } // namespace pkpy
 } // namespace pkpy
+
+
+// specialize std::less for PyVar
+namespace std {
+    template<>
+    struct less<pkpy::PyVar> {
+        bool operator()(const pkpy::PyVar& lhs, const pkpy::PyVar& rhs) const {
+            return memcmp(&lhs, &rhs, sizeof(pkpy::PyVar)) < 0;
+        }
+    };
+}

+ 1 - 1
include/pocketpy/str.h

@@ -128,7 +128,7 @@ struct StrName {
 
 
 struct SStream{
 struct SStream{
     PK_ALWAYS_PASS_BY_POINTER(SStream)
     PK_ALWAYS_PASS_BY_POINTER(SStream)
-    // pod_vector<T> is allocated by pool64 so the buffer can be moved into Str without a copy
+    // pod_vector<T> is allocated by pool128 so the buffer can be moved into Str without a copy
     pod_vector<char> buffer;
     pod_vector<char> buffer;
     int _precision = -1;
     int _precision = -1;
 
 

+ 6 - 10
include/pocketpy/vm.h

@@ -366,10 +366,10 @@ public:
     void check_compatible_type(PyVar obj, Type type){ if(!isinstance(obj, type)) TypeError(type, _tp(obj)); }
     void check_compatible_type(PyVar obj, Type type){ if(!isinstance(obj, type)) TypeError(type, _tp(obj)); }
 
 
     Type _tp(PyVar obj){ return obj.type; }
     Type _tp(PyVar obj){ return obj.type; }
-    const PyTypeInfo* _tp_info(PyVar obj) { return &_all_types[_tp(obj)]; }
-    const PyTypeInfo* _tp_info(Type type) { return &_all_types[type]; }
-    PyVar _t(PyVar obj){ return _all_types[_tp(obj)].obj; }
-    PyVar _t(Type type){ return _all_types[type].obj; }
+    const PyTypeInfo* _tp_info(PyVar obj) { return &_all_types[_tp(obj).index]; }
+    const PyTypeInfo* _tp_info(Type type) { return &_all_types[type.index]; }
+    PyVar _t(PyVar obj){ return _all_types[_tp(obj).index].obj; }
+    PyVar _t(Type type){ return _all_types[type.index].obj; }
 #endif
 #endif
 
 
 #if PK_REGION("User Type Registration")
 #if PK_REGION("User Type Registration")
@@ -480,14 +480,10 @@ PyVar py_var(VM* vm, __T&& value){
         return value ? vm->True : vm->False;
         return value ? vm->True : vm->False;
     }else if constexpr(is_integral_v<T>){
     }else if constexpr(is_integral_v<T>){
         // int
         // int
-        PyVar retval(VM::tp_int, true);
-        retval.as<i64>() = static_cast<i64>(value);
-        return retval;
+        return PyVar(VM::tp_int, static_cast<i64>(value));
     }else if constexpr(is_floating_point_v<T>){
     }else if constexpr(is_floating_point_v<T>){
         // float
         // float
-        PyVar retval(VM::tp_float, true);
-        retval.as<f64>() = static_cast<f64>(value);
-        return retval;
+        return PyVar(VM::tp_float, static_cast<f64>(value));
     }else if constexpr(std::is_pointer_v<T>){
     }else if constexpr(std::is_pointer_v<T>){
         return from_void_p(vm, (void*)value);
         return from_void_p(vm, (void*)value);
     }else{
     }else{

+ 3 - 3
src/ceval.cpp

@@ -898,9 +898,9 @@ __NEXT_STEP:;
         StrName _name(byte.arg);
         StrName _name(byte.arg);
         frame->_module->attr().set(_name, __curr_class);
         frame->_module->attr().set(_name, __curr_class);
         // call on_end_subclass
         // call on_end_subclass
-        PyTypeInfo* ti = &_all_types[PK_OBJ_GET(Type, __curr_class)];
+        PyTypeInfo* ti = &_all_types[PK_OBJ_GET(Type, __curr_class).index];
         if(ti->base != tp_object){
         if(ti->base != tp_object){
-            PyTypeInfo* base_ti = &_all_types[ti->base];
+            PyTypeInfo* base_ti = &_all_types[ti->base.index];
             if(base_ti->on_end_subclass) base_ti->on_end_subclass(this, ti);
             if(base_ti->on_end_subclass) base_ti->on_end_subclass(this, ti);
         }
         }
         __curr_class = nullptr;
         __curr_class = nullptr;
@@ -924,7 +924,7 @@ __NEXT_STEP:;
         PK_ASSERT(__curr_class != nullptr);
         PK_ASSERT(__curr_class != nullptr);
         StrName _name(byte.arg);
         StrName _name(byte.arg);
         Type type = PK_OBJ_GET(Type, __curr_class);
         Type type = PK_OBJ_GET(Type, __curr_class);
-        _all_types[type].annotated_fields.push_back(_name);
+        _all_types[type.index].annotated_fields.push_back(_name);
     } DISPATCH()
     } DISPATCH()
     /*****************************************/
     /*****************************************/
     case OP_WITH_ENTER:
     case OP_WITH_ENTER:

+ 4 - 4
src/dataclasses.cpp

@@ -13,7 +13,7 @@ static void patch__init__(VM* vm, Type cls){
         });
         });
 
 
         Type cls = vm->_tp(self);
         Type cls = vm->_tp(self);
-        const PyTypeInfo* cls_info = &vm->_all_types[cls];
+        const PyTypeInfo* cls_info = &vm->_all_types[cls.index];
         NameDict& cls_d = cls_info->obj->attr();
         NameDict& cls_d = cls_info->obj->attr();
         const auto& fields = cls_info->annotated_fields;
         const auto& fields = cls_info->annotated_fields;
 
 
@@ -46,7 +46,7 @@ static void patch__init__(VM* vm, Type cls){
 
 
 static void patch__repr__(VM* vm, Type cls){
 static void patch__repr__(VM* vm, Type cls){
     vm->bind__repr__(cls, [](VM* vm, PyVar _0) -> Str{
     vm->bind__repr__(cls, [](VM* vm, PyVar _0) -> Str{
-        const PyTypeInfo* cls_info = &vm->_all_types[vm->_tp(_0)];
+        const PyTypeInfo* cls_info = &vm->_all_types[vm->_tp(_0).index];
         const auto& fields = cls_info->annotated_fields;
         const auto& fields = cls_info->annotated_fields;
         const NameDict& obj_d = _0->attr();
         const NameDict& obj_d = _0->attr();
         SStream ss;
         SStream ss;
@@ -65,7 +65,7 @@ static void patch__repr__(VM* vm, Type cls){
 static void patch__eq__(VM* vm, Type cls){
 static void patch__eq__(VM* vm, Type cls){
     vm->bind__eq__(cls, [](VM* vm, PyVar _0, PyVar _1){
     vm->bind__eq__(cls, [](VM* vm, PyVar _0, PyVar _1){
         if(vm->_tp(_0) != vm->_tp(_1)) return vm->NotImplemented;
         if(vm->_tp(_0) != vm->_tp(_1)) return vm->NotImplemented;
-        const PyTypeInfo* cls_info = &vm->_all_types[vm->_tp(_0)];
+        const PyTypeInfo* cls_info = &vm->_all_types[vm->_tp(_0).index];
         const auto& fields = cls_info->annotated_fields;
         const auto& fields = cls_info->annotated_fields;
         for(StrName field: fields){
         for(StrName field: fields){
             PyVar lhs = _0->attr(field);
             PyVar lhs = _0->attr(field);
@@ -88,7 +88,7 @@ void add_module_dataclasses(VM* vm){
         if(!cls_d.contains(__repr__)) patch__repr__(vm, cls);
         if(!cls_d.contains(__repr__)) patch__repr__(vm, cls);
         if(!cls_d.contains(__eq__)) patch__eq__(vm, cls);
         if(!cls_d.contains(__eq__)) patch__eq__(vm, cls);
 
 
-        const auto& fields = vm->_all_types[cls].annotated_fields;
+        const auto& fields = vm->_all_types[cls.index].annotated_fields;
         bool has_default = false;
         bool has_default = false;
         for(StrName field: fields){
         for(StrName field: fields){
             if(cls_d.contains(field)){
             if(cls_d.contains(field)){

+ 7 - 7
src/pocketpy.cpp

@@ -104,7 +104,7 @@ void __init_builtins(VM* _vm) {
             StrName _1 = _type_name(vm, type);
             StrName _1 = _type_name(vm, type);
             vm->TypeError("super(): " + _0.escape() + " is not an instance of " + _1.escape());
             vm->TypeError("super(): " + _0.escape() + " is not an instance of " + _1.escape());
         }
         }
-        return vm->heap.gcnew<Super>(vm->tp_super, self_arg, vm->_all_types[type].base);
+        return vm->heap.gcnew<Super>(vm->tp_super, self_arg, vm->_all_types[type.index].base);
     });
     });
 
 
     _vm->bind_func(_vm->builtins, "staticmethod", 1, [](VM* vm, ArgsView args) {
     _vm->bind_func(_vm->builtins, "staticmethod", 1, [](VM* vm, ArgsView args) {
@@ -1502,7 +1502,7 @@ void VM::__post_init_builtin_types(){
 
 
     bind_func(tp_module, __new__, -1, PK_ACTION(vm->NotImplementedError()));
     bind_func(tp_module, __new__, -1, PK_ACTION(vm->NotImplementedError()));
 
 
-    _all_types[tp_module].m__getattr__ = [](VM* vm, PyVar obj, StrName name) -> PyVar{
+    _all_types[tp_module.index].m__getattr__ = [](VM* vm, PyVar obj, StrName name) -> PyVar{
         const Str& path = CAST(Str&, obj->attr(__path__));
         const Str& path = CAST(Str&, obj->attr(__path__));
         return vm->py_import(_S(path, ".", name.sv()), false);
         return vm->py_import(_S(path, ".", name.sv()), false);
     };
     };
@@ -1522,22 +1522,22 @@ void VM::__post_init_builtin_types(){
 
 
     bind__repr__(tp_type, [](VM* vm, PyVar self) -> Str{
     bind__repr__(tp_type, [](VM* vm, PyVar self) -> Str{
         SStream ss;
         SStream ss;
-        const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, self)];
+        const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, self).index];
         ss << "<class '" << info.name << "'>";
         ss << "<class '" << info.name << "'>";
         return ss.str();
         return ss.str();
     });
     });
 
 
     bind_property(_t(tp_object), "__class__", PK_LAMBDA(vm->_t(args[0])));
     bind_property(_t(tp_object), "__class__", PK_LAMBDA(vm->_t(args[0])));
     bind_property(_t(tp_type), "__base__", [](VM* vm, ArgsView args){
     bind_property(_t(tp_type), "__base__", [](VM* vm, ArgsView args){
-        const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0])];
-        return info.base.index == -1 ? vm->None : vm->_all_types[info.base].obj;
+        const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0]).index];
+        return info.base.index == -1 ? vm->None : vm->_all_types[info.base.index].obj;
     });
     });
     bind_property(_t(tp_type), "__name__", [](VM* vm, ArgsView args){
     bind_property(_t(tp_type), "__name__", [](VM* vm, ArgsView args){
-        const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0])];
+        const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0]).index];
         return VAR(info.name.sv());
         return VAR(info.name.sv());
     });
     });
     bind_property(_t(tp_type), "__module__", [](VM* vm, ArgsView args){
     bind_property(_t(tp_type), "__module__", [](VM* vm, ArgsView args){
-        const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0])];
+        const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0]).index];
         if(info.mod == nullptr) return vm->None;
         if(info.mod == nullptr) return vm->None;
         return info.mod;
         return info.mod;
     });
     });

+ 3 - 3
src/str.cpp

@@ -17,7 +17,7 @@ int utf8len(unsigned char c, bool suppress){
         if(this->size < (int)sizeof(this->_inlined)){       \
         if(this->size < (int)sizeof(this->_inlined)){       \
             this->data = this->_inlined;                    \
             this->data = this->_inlined;                    \
         }else{                                              \
         }else{                                              \
-            this->data = (char*)pool64_alloc(this->size+1); \
+            this->data = (char*)pool128_alloc(this->size+1); \
         }
         }
 
 
 #define PK_STR_COPY_INIT(__s)  \
 #define PK_STR_COPY_INIT(__s)  \
@@ -97,7 +97,7 @@ int utf8len(unsigned char c, bool suppress){
     }
     }
 
 
     Str& Str::operator=(const Str& other){
     Str& Str::operator=(const Str& other){
-        if(!is_inlined()) pool64_dealloc(data);
+        if(!is_inlined()) pool128_dealloc(data);
         size = other.size;
         size = other.size;
         is_ascii = other.is_ascii;
         is_ascii = other.is_ascii;
         PK_STR_ALLOCATE()
         PK_STR_ALLOCATE()
@@ -168,7 +168,7 @@ int utf8len(unsigned char c, bool suppress){
     }
     }
 
 
     Str::~Str(){
     Str::~Str(){
-        if(!is_inlined()) pool64_dealloc(data);
+        if(!is_inlined()) pool128_dealloc(data);
     }
     }
 
 
     Str Str::substr(int start, int len) const {
     Str Str::substr(int start, int len) const {

+ 27 - 27
src/vm.cpp

@@ -148,7 +148,7 @@ namespace pkpy{
         do{
         do{
             val = _t(cls)->attr().try_get(name);
             val = _t(cls)->attr().try_get(name);
             if(val != nullptr) return val;
             if(val != nullptr) return val;
-            cls = _all_types[cls].base;
+            cls = _all_types[cls.index].base;
             if(cls.index == -1) break;
             if(cls.index == -1) break;
         }while(true);
         }while(true);
         return nullptr;
         return nullptr;
@@ -161,7 +161,7 @@ namespace pkpy{
     bool VM::issubclass(Type cls, Type base){
     bool VM::issubclass(Type cls, Type base){
         do{
         do{
             if(cls == base) return true;
             if(cls == base) return true;
-            Type next = _all_types[cls].base;
+            Type next = _all_types[cls.index].base;
             if(next.index == -1) break;
             if(next.index == -1) break;
             cls = next;
             cls = next;
         }while(true);
         }while(true);
@@ -207,7 +207,7 @@ namespace pkpy{
 
 
     PyVar VM::new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled){
     PyVar VM::new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled){
         PyVar obj = heap._new<Type>(tp_type, Type(_all_types.size()));
         PyVar obj = heap._new<Type>(tp_type, Type(_all_types.size()));
-        const PyTypeInfo& base_info = _all_types[base];
+        const PyTypeInfo& base_info = _all_types[base.index];
         if(!base_info.subclass_enabled){
         if(!base_info.subclass_enabled){
             Str error = _S("type ", base_info.name.escape(), " is not `subclass_enabled`");
             Str error = _S("type ", base_info.name.escape(), " is not `subclass_enabled`");
             throw std::runtime_error(error.c_str());
             throw std::runtime_error(error.c_str());
@@ -280,10 +280,10 @@ namespace pkpy{
     bool VM::py_callable(PyVar obj){
     bool VM::py_callable(PyVar obj){
         Type cls = vm->_tp(obj);
         Type cls = vm->_tp(obj);
         switch(cls.index){
         switch(cls.index){
-            case VM::tp_function.index: return vm->True;
-            case VM::tp_native_func.index: return vm->True;
-            case VM::tp_bound_method.index: return vm->True;
-            case VM::tp_type.index: return vm->True;
+            case VM::tp_function.index: return true;
+            case VM::tp_native_func.index: return true;
+            case VM::tp_bound_method.index: return true;
+            case VM::tp_type.index: return true;
         }
         }
         return vm->find_name_in_mro(cls, __call__) != nullptr;
         return vm->find_name_in_mro(cls, __call__) != nullptr;
     }
     }
@@ -501,7 +501,7 @@ i64 VM::py_hash(PyVar obj){
         return CAST(i64, ret);
         return CAST(i64, ret);
     }
     }
     // if it is trivial `object`, return PK_BITS
     // if it is trivial `object`, return PK_BITS
-    if(ti == &_all_types[tp_object]) return obj.hash();
+    if(ti == &_all_types[tp_object.index]) return obj.hash();
     // otherwise, we check if it has a custom __eq__ other than object.__eq__
     // otherwise, we check if it has a custom __eq__ other than object.__eq__
     bool has_custom_eq = false;
     bool has_custom_eq = false;
     if(ti->m__eq__) has_custom_eq = true;
     if(ti->m__eq__) has_custom_eq = true;
@@ -868,7 +868,7 @@ void VM::__init_builtin_types(){
     this->Ellipsis = heap._new<Dummy>(_new_type("ellipsis"));
     this->Ellipsis = heap._new<Dummy>(_new_type("ellipsis"));
     this->True = heap._new<Dummy>(tp_bool);
     this->True = heap._new<Dummy>(tp_bool);
     this->False = heap._new<Dummy>(tp_bool);
     this->False = heap._new<Dummy>(tp_bool);
-    this->StopIteration = _all_types[_new_type("StopIteration", tp_exception)].obj;
+    this->StopIteration = _all_types[_new_type("StopIteration", tp_exception).index].obj;
 
 
     this->builtins = new_module("builtins");
     this->builtins = new_module("builtins");
     
     
@@ -1182,7 +1182,7 @@ PyVar VM::getattr(PyVar obj, StrName name, bool throw_err){
     if(cls_var != nullptr){
     if(cls_var != nullptr){
         // bound method is non-data descriptor
         // bound method is non-data descriptor
         if(!is_tagged(cls_var)){
         if(!is_tagged(cls_var)){
-            switch(cls_var.type){
+            switch(cls_var.type.index){
                 case tp_function.index:
                 case tp_function.index:
                     return VAR(BoundMethod(obj, cls_var));
                     return VAR(BoundMethod(obj, cls_var));
                 case tp_native_func.index:
                 case tp_native_func.index:
@@ -1196,7 +1196,7 @@ PyVar VM::getattr(PyVar obj, StrName name, bool throw_err){
         return cls_var;
         return cls_var;
     }
     }
 
 
-    const PyTypeInfo* ti = &_all_types[objtype];
+    const PyTypeInfo* ti = &_all_types[objtype.index];
     if(ti->m__getattr__){
     if(ti->m__getattr__){
         PyVar ret = ti->m__getattr__(this, obj, name);
         PyVar ret = ti->m__getattr__(this, obj, name);
         if(ret) return ret;
         if(ret) return ret;
@@ -1249,7 +1249,7 @@ PyVar VM::get_unbound_method(PyVar obj, StrName name, PyVar* self, bool throw_er
 
 
     if(cls_var != nullptr){
     if(cls_var != nullptr){
         if(!is_tagged(cls_var)){
         if(!is_tagged(cls_var)){
-            switch(cls_var.type){
+            switch(cls_var.type.index){
                 case tp_function.index:
                 case tp_function.index:
                     *self = obj;
                     *self = obj;
                     break;
                     break;
@@ -1267,7 +1267,7 @@ PyVar VM::get_unbound_method(PyVar obj, StrName name, PyVar* self, bool throw_er
         return cls_var;
         return cls_var;
     }
     }
 
 
-    const PyTypeInfo* ti = &_all_types[objtype];
+    const PyTypeInfo* ti = &_all_types[objtype.index];
     if(fallback && ti->m__getattr__){
     if(fallback && ti->m__getattr__){
         PyVar ret = ti->m__getattr__(this, obj, name);
         PyVar ret = ti->m__getattr__(this, obj, name);
         if(ret) return ret;
         if(ret) return ret;
@@ -1301,7 +1301,7 @@ void VM::setattr(PyVar obj, StrName name, PyVar value){
         }
         }
     }
     }
 
 
-    const PyTypeInfo* ti = &_all_types[objtype];
+    const PyTypeInfo* ti = &_all_types[objtype.index];
     if(ti->m__setattr__){
     if(ti->m__setattr__){
         ti->m__setattr__(this, obj, name, value);
         ti->m__setattr__(this, obj, name, value);
         return;
         return;
@@ -1429,7 +1429,7 @@ void ManagedHeap::mark() {
 }
 }
 
 
 StrName _type_name(VM *vm, Type type){
 StrName _type_name(VM *vm, Type type){
-    return vm->_all_types[type].name;
+    return vm->_all_types[type.index].name;
 }
 }
 
 
 void _gc_mark_namedict(NameDict* t){
 void _gc_mark_namedict(NameDict* t){
@@ -1439,14 +1439,14 @@ void _gc_mark_namedict(NameDict* t){
 }
 }
 
 
 void VM::bind__getitem__(Type type, PyVar (*f)(VM*, PyVar, PyVar)){
 void VM::bind__getitem__(Type type, PyVar (*f)(VM*, PyVar, PyVar)){
-    _all_types[type].m__getitem__ = f;
+    _all_types[type.index].m__getitem__ = f;
     bind_func(type, __getitem__, 2, [](VM* vm, ArgsView args){
     bind_func(type, __getitem__, 2, [](VM* vm, ArgsView args){
         return lambda_get_userdata<PyVar(*)(VM*, PyVar, PyVar)>(args.begin())(vm, args[0], args[1]);
         return lambda_get_userdata<PyVar(*)(VM*, PyVar, PyVar)>(args.begin())(vm, args[0], args[1]);
     }, f);
     }, f);
 }
 }
 
 
 void VM::bind__setitem__(Type type, void (*f)(VM*, PyVar, PyVar, PyVar)){
 void VM::bind__setitem__(Type type, void (*f)(VM*, PyVar, PyVar, PyVar)){
-    _all_types[type].m__setitem__ = f;
+    _all_types[type.index].m__setitem__ = f;
     bind_func(type, __setitem__, 3, [](VM* vm, ArgsView args){
     bind_func(type, __setitem__, 3, [](VM* vm, ArgsView args){
         lambda_get_userdata<void(*)(VM* vm, PyVar, PyVar, PyVar)>(args.begin())(vm, args[0], args[1], args[2]);
         lambda_get_userdata<void(*)(VM* vm, PyVar, PyVar, PyVar)>(args.begin())(vm, args[0], args[1], args[2]);
         return vm->None;
         return vm->None;
@@ -1454,7 +1454,7 @@ void VM::bind__setitem__(Type type, void (*f)(VM*, PyVar, PyVar, PyVar)){
 }
 }
 
 
 void VM::bind__delitem__(Type type, void (*f)(VM*, PyVar, PyVar)){
 void VM::bind__delitem__(Type type, void (*f)(VM*, PyVar, PyVar)){
-    _all_types[type].m__delitem__ = f;
+    _all_types[type.index].m__delitem__ = f;
     bind_func(type, __delitem__, 2, [](VM* vm, ArgsView args){
     bind_func(type, __delitem__, 2, [](VM* vm, ArgsView args){
         lambda_get_userdata<void(*)(VM*, PyVar, PyVar)>(args.begin())(vm, args[0], args[1]);
         lambda_get_userdata<void(*)(VM*, PyVar, PyVar)>(args.begin())(vm, args[0], args[1]);
         return vm->None;
         return vm->None;
@@ -1470,7 +1470,7 @@ PyVar VM::__pack_next_retval(unsigned n){
 }
 }
 
 
 void VM::bind__next__(Type type, unsigned (*f)(VM*, PyVar)){
 void VM::bind__next__(Type type, unsigned (*f)(VM*, PyVar)){
-    _all_types[type].m__next__ = f;
+    _all_types[type.index].m__next__ = f;
     bind_func(type, __next__, 1, [](VM* vm, ArgsView args){
     bind_func(type, __next__, 1, [](VM* vm, ArgsView args){
         int n = lambda_get_userdata<unsigned(*)(VM*, PyVar)>(args.begin())(vm, args[0]);
         int n = lambda_get_userdata<unsigned(*)(VM*, PyVar)>(args.begin())(vm, args[0]);
         return vm->__pack_next_retval(n);
         return vm->__pack_next_retval(n);
@@ -1485,10 +1485,10 @@ void VM::bind__next__(Type type, PyVar (*f)(VM*, PyVar)){
 }
 }
 
 
 #define BIND_UNARY_SPECIAL(name)                                                        \
 #define BIND_UNARY_SPECIAL(name)                                                        \
-    void VM::bind##name(Type type, PyVar (*f)(VM*, PyVar)){                     \
-        _all_types[type].m##name = f;                                                   \
+    void VM::bind##name(Type type, PyVar (*f)(VM*, PyVar)){                             \
+        _all_types[type.index].m##name = f;                                             \
         bind_func(type, name, 1, [](VM* vm, ArgsView args){                             \
         bind_func(type, name, 1, [](VM* vm, ArgsView args){                             \
-            return lambda_get_userdata<PyVar(*)(VM*, PyVar)>(args.begin())(vm, args[0]);    \
+            return lambda_get_userdata<PyVar(*)(VM*, PyVar)>(args.begin())(vm, args[0]);\
         }, f);                                                                          \
         }, f);                                                                          \
     }
     }
     BIND_UNARY_SPECIAL(__iter__)
     BIND_UNARY_SPECIAL(__iter__)
@@ -1497,7 +1497,7 @@ void VM::bind__next__(Type type, PyVar (*f)(VM*, PyVar)){
 #undef BIND_UNARY_SPECIAL
 #undef BIND_UNARY_SPECIAL
 
 
 void VM::bind__str__(Type type, Str (*f)(VM*, PyVar)){
 void VM::bind__str__(Type type, Str (*f)(VM*, PyVar)){
-    _all_types[type].m__str__ = f;
+    _all_types[type.index].m__str__ = f;
     bind_func(type, __str__, 1, [](VM* vm, ArgsView args){
     bind_func(type, __str__, 1, [](VM* vm, ArgsView args){
         Str s = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
         Str s = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
         return VAR(s);
         return VAR(s);
@@ -1505,7 +1505,7 @@ void VM::bind__str__(Type type, Str (*f)(VM*, PyVar)){
 }
 }
 
 
 void VM::bind__repr__(Type type, Str (*f)(VM*, PyVar)){
 void VM::bind__repr__(Type type, Str (*f)(VM*, PyVar)){
-    _all_types[type].m__repr__ = f;
+    _all_types[type.index].m__repr__ = f;
     bind_func(type, __repr__, 1, [](VM* vm, ArgsView args){
     bind_func(type, __repr__, 1, [](VM* vm, ArgsView args){
         Str s = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
         Str s = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
         return VAR(s);
         return VAR(s);
@@ -1513,7 +1513,7 @@ void VM::bind__repr__(Type type, Str (*f)(VM*, PyVar)){
 }
 }
 
 
 void VM::bind__hash__(Type type, i64 (*f)(VM*, PyVar)){
 void VM::bind__hash__(Type type, i64 (*f)(VM*, PyVar)){
-    _all_types[type].m__hash__ = f;
+    _all_types[type.index].m__hash__ = f;
     bind_func(type, __hash__, 1, [](VM* vm, ArgsView args){
     bind_func(type, __hash__, 1, [](VM* vm, ArgsView args){
         i64 ret = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
         i64 ret = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
         return VAR(ret);
         return VAR(ret);
@@ -1521,7 +1521,7 @@ void VM::bind__hash__(Type type, i64 (*f)(VM*, PyVar)){
 }
 }
 
 
 void VM::bind__len__(Type type, i64 (*f)(VM*, PyVar)){
 void VM::bind__len__(Type type, i64 (*f)(VM*, PyVar)){
-    _all_types[type].m__len__ = f;
+    _all_types[type.index].m__len__ = f;
     bind_func(type, __len__, 1, [](VM* vm, ArgsView args){
     bind_func(type, __len__, 1, [](VM* vm, ArgsView args){
         i64 ret = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
         i64 ret = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
         return VAR(ret);
         return VAR(ret);
@@ -1531,7 +1531,7 @@ void VM::bind__len__(Type type, i64 (*f)(VM*, PyVar)){
 
 
 #define BIND_BINARY_SPECIAL(name)                                                       \
 #define BIND_BINARY_SPECIAL(name)                                                       \
     void VM::bind##name(Type type, BinaryFuncC f){                                      \
     void VM::bind##name(Type type, BinaryFuncC f){                                      \
-        _all_types[type].m##name = f;                                                   \
+        _all_types[type.index].m##name = f;                                                   \
         bind_func(type, name, 2, [](VM* vm, ArgsView args){                             \
         bind_func(type, name, 2, [](VM* vm, ArgsView args){                             \
             return lambda_get_userdata<BinaryFuncC>(args.begin())(vm, args[0], args[1]);\
             return lambda_get_userdata<BinaryFuncC>(args.begin())(vm, args[0], args[1]);\
         }, f);                                                                          \
         }, f);                                                                          \