diff --git a/include/pocketpy/cffi.h b/include/pocketpy/cffi.h index a0da20be..cf7aa952 100644 --- a/include/pocketpy/cffi.h +++ b/include/pocketpy/cffi.h @@ -6,9 +6,9 @@ namespace pkpy { #define PY_CLASS(T, mod, name) \ - [[deprecated]] static Type _type(VM* vm) { return vm->_cxx_typeid_map[typeid(T)]; } \ - [[deprecated]] static PyVar register_class(VM* vm, PyVar mod, Type base=Type(0)) { \ - return vm->register_user_class(mod, #name, base); \ + [[deprecated]] static Type _type(VM* vm) { return vm->_cxx_typeid_map[typeid(T)]; } \ + [[deprecated]] static PyVar register_class(VM* vm, PyVar mod, Type base=VM::tp_object) { \ + return vm->register_user_class(mod, #name, base); \ } struct VoidP{ diff --git a/include/pocketpy/common.h b/include/pocketpy/common.h index 68b172cd..e63eeda0 100644 --- a/include/pocketpy/common.h +++ b/include/pocketpy/common.h @@ -98,11 +98,11 @@ struct Discarded { }; struct Type { int16_t index; - constexpr Type(): index(-1) {} + constexpr Type(): index(0) {} 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; } - explicit operator bool() const { return index != -1; } + constexpr operator int() const { return index; } }; #define PK_LAMBDA(x) ([](VM* vm, ArgsView args) { return x; }) @@ -178,7 +178,11 @@ struct PyVar final{ char _bytes[12]; // uninitialized +#if PK_DEBUG_EXTRA_CHECK PyVar(): type() { } +#else + PyVar() = default; +#endif // zero initialized PyVar(std::nullptr_t): type(), is_sso(false), flags(0), _bytes{0} { } // PyObject* initialized (is_sso = false) diff --git a/include/pocketpy/config.h b/include/pocketpy/config.h index 44b1c388..61630b54 100644 --- a/include/pocketpy/config.h +++ b/include/pocketpy/config.h @@ -33,11 +33,11 @@ /*************** debug settings ***************/ // Enable this may help you find bugs -#define PK_DEBUG_EXTRA_CHECK 0 +#define PK_DEBUG_EXTRA_CHECK 1 // Do not edit the following settings unless you know what you are doing #define PK_DEBUG_CEVAL_STEP 0 -#define PK_DEBUG_MEMORY_POOL 0 +#define PK_DEBUG_MEMORY_POOL 1 #define PK_DEBUG_NO_MEMORY_POOL 0 #define PK_DEBUG_NO_AUTO_GC 0 #define PK_DEBUG_GC_STATS 0 diff --git a/include/pocketpy/obj.h b/include/pocketpy/obj.h index 7bc897fc..394630ea 100644 --- a/include/pocketpy/obj.h +++ b/include/pocketpy/obj.h @@ -124,8 +124,8 @@ struct PyObject{ } }; -const int kTpIntIndex = 2; -const int kTpFloatIndex = 3; +const int kTpIntIndex = 3; +const int kTpFloatIndex = 4; inline bool is_tagged(PyVar p) noexcept { return p.is_sso; } inline bool is_float(PyVar p) noexcept { return p.type.index == kTpFloatIndex; } diff --git a/include/pocketpy/vm.h b/include/pocketpy/vm.h index 34f1748d..4ac6cfb1 100644 --- a/include/pocketpy/vm.h +++ b/include/pocketpy/vm.h @@ -173,14 +173,14 @@ public: // function _import_handler; // for quick access - static constexpr Type tp_object=Type(0), tp_type=Type(1); - static constexpr Type tp_int=Type(kTpIntIndex), tp_float=Type(kTpFloatIndex), tp_bool=Type(4), tp_str=Type(5); - static constexpr Type tp_list=Type(6), tp_tuple=Type(7); - static constexpr Type tp_slice=Type(8), tp_range=Type(9), tp_module=Type(10); - static constexpr Type tp_function=Type(11), tp_native_func=Type(12), tp_bound_method=Type(13); - static constexpr Type tp_super=Type(14), tp_exception=Type(15), tp_bytes=Type(16), tp_mappingproxy=Type(17); - static constexpr Type tp_dict=Type(18), tp_property=Type(19), tp_star_wrapper=Type(20); - static constexpr Type tp_staticmethod=Type(21), tp_classmethod=Type(22); + static constexpr Type tp_object=Type(1), tp_type=Type(2); + static constexpr Type tp_int=Type(kTpIntIndex), tp_float=Type(kTpFloatIndex), tp_bool=Type(5), tp_str=Type(6); + static constexpr Type tp_list=Type(7), tp_tuple=Type(8); + static constexpr Type tp_slice=Type(9), tp_range=Type(10), tp_module=Type(11); + static constexpr Type tp_function=Type(12), tp_native_func=Type(13), tp_bound_method=Type(14); + static constexpr Type tp_super=Type(15), tp_exception=Type(16), tp_bytes=Type(17), tp_mappingproxy=Type(18); + static constexpr Type tp_dict=Type(19), tp_property=Type(20), tp_star_wrapper=Type(21); + static constexpr Type tp_staticmethod=Type(22), tp_classmethod=Type(23); const bool enable_os; VM(bool enable_os=true); @@ -366,10 +366,10 @@ public: void check_compatible_type(PyVar obj, Type type){ if(!isinstance(obj, type)) TypeError(type, _tp(obj)); } Type _tp(PyVar obj){ return obj.type; } - 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; } + 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; } #endif #if PK_REGION("User Type Registration") @@ -445,7 +445,7 @@ inline constexpr bool is_immutable_v = is_integral_v || is_floating_point_v || std::is_same_v || std::is_pointer_v || std::is_enum_v; -template constexpr Type _find_type_in_const_cxx_typeid_map(){ return Type(-1); } +template constexpr Type _find_type_in_const_cxx_typeid_map(){ return Type(); } template<> constexpr Type _find_type_in_const_cxx_typeid_map(){ return VM::tp_str; } template<> constexpr Type _find_type_in_const_cxx_typeid_map(){ return VM::tp_list; } template<> constexpr Type _find_type_in_const_cxx_typeid_map(){ return VM::tp_tuple; } @@ -488,7 +488,7 @@ PyVar py_var(VM* vm, __T&& value){ return from_void_p(vm, (void*)value); }else{ constexpr Type const_type = _find_type_in_const_cxx_typeid_map(); - if constexpr(const_type.index >= 0){ + if constexpr(const_type){ return vm->heap.gcnew(const_type, std::forward<__T>(value)); } } @@ -542,7 +542,7 @@ __T _py_cast__internal(VM* vm, PyVar obj) { return to_void_p(vm, obj); }else{ constexpr Type const_type = _find_type_in_const_cxx_typeid_map(); - if constexpr(const_type.index >= 0){ + if constexpr(const_type){ if constexpr(with_check){ if constexpr(std::is_same_v){ // Exception is `subclass_enabled` diff --git a/src/ceval.cpp b/src/ceval.cpp index 6f6684eb..683ee46e 100644 --- a/src/ceval.cpp +++ b/src/ceval.cpp @@ -898,9 +898,9 @@ __NEXT_STEP:; StrName _name(byte.arg); frame->_module->attr().set(_name, __curr_class); // call on_end_subclass - PyTypeInfo* ti = &_all_types[PK_OBJ_GET(Type, __curr_class).index]; + PyTypeInfo* ti = &_all_types[PK_OBJ_GET(Type, __curr_class)]; if(ti->base != tp_object){ - PyTypeInfo* base_ti = &_all_types[ti->base.index]; + PyTypeInfo* base_ti = &_all_types[ti->base]; if(base_ti->on_end_subclass) base_ti->on_end_subclass(this, ti); } __curr_class = nullptr; @@ -924,7 +924,7 @@ __NEXT_STEP:; PK_ASSERT(__curr_class != nullptr); StrName _name(byte.arg); Type type = PK_OBJ_GET(Type, __curr_class); - _all_types[type.index].annotated_fields.push_back(_name); + _all_types[type].annotated_fields.push_back(_name); } DISPATCH() /*****************************************/ case OP_WITH_ENTER: diff --git a/src/dataclasses.cpp b/src/dataclasses.cpp index 212c3558..842b5873 100644 --- a/src/dataclasses.cpp +++ b/src/dataclasses.cpp @@ -13,7 +13,7 @@ static void patch__init__(VM* vm, Type cls){ }); Type cls = vm->_tp(self); - const PyTypeInfo* cls_info = &vm->_all_types[cls.index]; + const PyTypeInfo* cls_info = &vm->_all_types[cls]; NameDict& cls_d = cls_info->obj->attr(); 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){ vm->bind__repr__(cls, [](VM* vm, PyVar _0) -> Str{ - const PyTypeInfo* cls_info = &vm->_all_types[vm->_tp(_0).index]; + const PyTypeInfo* cls_info = &vm->_all_types[vm->_tp(_0)]; const auto& fields = cls_info->annotated_fields; const NameDict& obj_d = _0->attr(); SStream ss; @@ -65,7 +65,7 @@ static void patch__repr__(VM* vm, Type cls){ static void patch__eq__(VM* vm, Type cls){ vm->bind__eq__(cls, [](VM* vm, PyVar _0, PyVar _1){ if(vm->_tp(_0) != vm->_tp(_1)) return vm->NotImplemented; - const PyTypeInfo* cls_info = &vm->_all_types[vm->_tp(_0).index]; + const PyTypeInfo* cls_info = &vm->_all_types[vm->_tp(_0)]; const auto& fields = cls_info->annotated_fields; for(StrName field: fields){ 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(__eq__)) patch__eq__(vm, cls); - const auto& fields = vm->_all_types[cls.index].annotated_fields; + const auto& fields = vm->_all_types[cls].annotated_fields; bool has_default = false; for(StrName field: fields){ if(cls_d.contains(field)){ diff --git a/src/modules.cpp b/src/modules.cpp index 0977901e..77040ba4 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -239,7 +239,7 @@ void add_module_enum(VM* vm){ CodeObject_ code = vm->compile(kPythonLibs__enum, "enum.py", EXEC_MODE); vm->_exec(code, mod); PyVar Enum = mod->attr("Enum"); - vm->_all_types[PK_OBJ_GET(Type, Enum).index].on_end_subclass = \ + vm->_all_types[PK_OBJ_GET(Type, Enum)].on_end_subclass = \ [](VM* vm, PyTypeInfo* new_ti){ new_ti->subclass_enabled = false; // Enum class cannot be subclassed twice NameDict& attr = new_ti->obj->attr(); diff --git a/src/pocketpy.cpp b/src/pocketpy.cpp index 9394b7ae..10069b50 100644 --- a/src/pocketpy.cpp +++ b/src/pocketpy.cpp @@ -104,7 +104,7 @@ void __init_builtins(VM* _vm) { StrName _1 = _type_name(vm, type); vm->TypeError("super(): " + _0.escape() + " is not an instance of " + _1.escape()); } - return vm->heap.gcnew(vm->tp_super, self_arg, vm->_all_types[type.index].base); + return vm->heap.gcnew(vm->tp_super, self_arg, vm->_all_types[type].base); }); _vm->bind_func(_vm->builtins, "staticmethod", 1, [](VM* vm, ArgsView args) { @@ -406,14 +406,14 @@ void __init_builtins(VM* _vm) { if(args.size() == 1+0) return VAR(0); // 1 arg if(args.size() == 1+1){ - switch(vm->_tp(args[1]).index){ - case VM::tp_float.index: + switch(vm->_tp(args[1])){ + case VM::tp_float: return VAR((i64)_CAST(f64, args[1])); - case VM::tp_int.index: + case VM::tp_int: return args[1]; - case VM::tp_bool.index: + case VM::tp_bool: return VAR(args[1]==vm->True ? 1 : 0); - case VM::tp_str.index: + case VM::tp_str: break; default: vm->TypeError("invalid arguments for int()"); @@ -483,14 +483,14 @@ void __init_builtins(VM* _vm) { if(args.size() == 1+0) return VAR(0.0); if(args.size() > 1+1) vm->TypeError("float() takes at most 1 argument"); // 1 arg - switch(vm->_tp(args[1]).index){ - case VM::tp_int.index: + switch(vm->_tp(args[1])){ + case VM::tp_int: return VAR((f64)CAST(i64, args[1])); - case VM::tp_float.index: + case VM::tp_float: return args[1]; - case VM::tp_bool.index: + case VM::tp_bool: return VAR(args[1]==vm->True ? 1.0 : 0.0); - case VM::tp_str.index: + case VM::tp_str: break; default: vm->TypeError("invalid arguments for float()"); @@ -1502,7 +1502,7 @@ void VM::__post_init_builtin_types(){ bind_func(tp_module, __new__, -1, PK_ACTION(vm->NotImplementedError())); - _all_types[tp_module.index].m__getattr__ = [](VM* vm, PyVar obj, StrName name) -> PyVar{ + _all_types[tp_module].m__getattr__ = [](VM* vm, PyVar obj, StrName name) -> PyVar{ const Str& path = CAST(Str&, obj->attr(__path__)); 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{ SStream ss; - const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, self).index]; + const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, self)]; ss << ""; return ss.str(); }); bind_property(_t(tp_object), "__class__", PK_LAMBDA(vm->_t(args[0]))); bind_property(_t(tp_type), "__base__", [](VM* vm, ArgsView args){ - 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; + 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; }); bind_property(_t(tp_type), "__name__", [](VM* vm, ArgsView args){ - const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0]).index]; + const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0])]; return VAR(info.name.sv()); }); bind_property(_t(tp_type), "__module__", [](VM* vm, ArgsView args){ - const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0]).index]; + const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0])]; if(info.mod == nullptr) return vm->None; return info.mod; }); diff --git a/src/vm.cpp b/src/vm.cpp index 7fae50db..fcb47bd6 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -148,7 +148,7 @@ namespace pkpy{ do{ val = _t(cls)->attr().try_get(name); if(val != nullptr) return val; - cls = _all_types[cls.index].base; + cls = _all_types[cls].base; if(cls.index == -1) break; }while(true); return nullptr; @@ -161,7 +161,7 @@ namespace pkpy{ bool VM::issubclass(Type cls, Type base){ do{ if(cls == base) return true; - Type next = _all_types[cls.index].base; + Type next = _all_types[cls].base; if(next.index == -1) break; cls = next; }while(true); @@ -206,8 +206,8 @@ namespace pkpy{ } PyVar VM::new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled){ - PyVar obj = heap._new(tp_type, Type(_all_types.size())); - const PyTypeInfo& base_info = _all_types[base.index]; + PyVar obj = heap._new(tp_type, Type(_all_types.size()+1)); + const PyTypeInfo& base_info = _all_types[base]; if(!base_info.subclass_enabled){ Str error = _S("type ", base_info.name.escape(), " is not `subclass_enabled`"); throw std::runtime_error(error.c_str()); @@ -501,7 +501,7 @@ i64 VM::py_hash(PyVar obj){ return CAST(i64, ret); } // if it is trivial `object`, return PK_BITS - if(ti == &_all_types[tp_object.index]) return obj.hash(); + if(ti == &_all_types[tp_object]) return obj.hash(); // otherwise, we check if it has a custom __eq__ other than object.__eq__ bool has_custom_eq = false; if(ti->m__eq__) has_custom_eq = true; @@ -825,10 +825,10 @@ void VM::__log_s_data(const char* title) { #endif void VM::__init_builtin_types(){ - _all_types.push_back({heap._new(Type(1), Type(0)), Type(-1), nullptr, "object", true}); - _all_types.push_back({heap._new(Type(1), Type(1)), Type(0), nullptr, "type", false}); + _all_types.push_back({heap._new(tp_type, tp_object), Type(), nullptr, "object", true}); + _all_types.push_back({heap._new(tp_type, tp_type), tp_object, nullptr, "type", false}); - auto _new_type = [this](const char* name, Type base=Type(0), bool subclass_enabled=false){ + auto _new_type = [this](const char* name, Type base=tp_object, bool subclass_enabled=false){ PyVar obj = new_type_object(nullptr, name, base, subclass_enabled); return PK_OBJ_GET(Type, obj); }; @@ -849,10 +849,10 @@ void VM::__init_builtin_types(){ if(tp_bound_method != _new_type("bound_method")) exit(-3); if(tp_super != _new_type("super")) exit(-3); - if(tp_exception != _new_type("Exception", Type(0), true)) exit(-3); + if(tp_exception != _new_type("Exception", tp_object, true)) exit(-3); if(tp_bytes != _new_type("bytes")) exit(-3); if(tp_mappingproxy != _new_type("mappingproxy")) exit(-3); - if(tp_dict != _new_type("dict", Type(0), true)) exit(-3); // dict can be subclassed + if(tp_dict != _new_type("dict", tp_object, true)) exit(-3); // dict can be subclassed if(tp_property != _new_type("property")) exit(-3); if(tp_star_wrapper != _new_type("_star_wrapper")) exit(-3); @@ -868,7 +868,7 @@ void VM::__init_builtin_types(){ this->Ellipsis = heap._new(_new_type("ellipsis")); this->True = heap._new(tp_bool); this->False = heap._new(tp_bool); - this->StopIteration = _all_types[_new_type("StopIteration", tp_exception).index].obj; + this->StopIteration = _all_types[_new_type("StopIteration", tp_exception)].obj; this->builtins = new_module("builtins"); @@ -1196,7 +1196,7 @@ PyVar VM::getattr(PyVar obj, StrName name, bool throw_err){ return cls_var; } - const PyTypeInfo* ti = &_all_types[objtype.index]; + const PyTypeInfo* ti = &_all_types[objtype]; if(ti->m__getattr__){ PyVar ret = ti->m__getattr__(this, obj, name); if(ret) return ret; @@ -1267,7 +1267,7 @@ PyVar VM::get_unbound_method(PyVar obj, StrName name, PyVar* self, bool throw_er return cls_var; } - const PyTypeInfo* ti = &_all_types[objtype.index]; + const PyTypeInfo* ti = &_all_types[objtype]; if(fallback && ti->m__getattr__){ PyVar ret = ti->m__getattr__(this, obj, name); if(ret) return ret; @@ -1301,7 +1301,7 @@ void VM::setattr(PyVar obj, StrName name, PyVar value){ } } - const PyTypeInfo* ti = &_all_types[objtype.index]; + const PyTypeInfo* ti = &_all_types[objtype]; if(ti->m__setattr__){ ti->m__setattr__(this, obj, name, value); return; @@ -1429,7 +1429,7 @@ void ManagedHeap::mark() { } StrName _type_name(VM *vm, Type type){ - return vm->_all_types[type.index].name; + return vm->_all_types[type].name; } 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)){ - _all_types[type.index].m__getitem__ = f; + _all_types[type].m__getitem__ = f; bind_func(type, __getitem__, 2, [](VM* vm, ArgsView args){ return lambda_get_userdata(args.begin())(vm, args[0], args[1]); }, f); } void VM::bind__setitem__(Type type, void (*f)(VM*, PyVar, PyVar, PyVar)){ - _all_types[type.index].m__setitem__ = f; + _all_types[type].m__setitem__ = f; bind_func(type, __setitem__, 3, [](VM* vm, ArgsView args){ lambda_get_userdata(args.begin())(vm, args[0], args[1], args[2]); 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)){ - _all_types[type.index].m__delitem__ = f; + _all_types[type].m__delitem__ = f; bind_func(type, __delitem__, 2, [](VM* vm, ArgsView args){ lambda_get_userdata(args.begin())(vm, args[0], args[1]); return vm->None; @@ -1470,7 +1470,7 @@ PyVar VM::__pack_next_retval(unsigned n){ } void VM::bind__next__(Type type, unsigned (*f)(VM*, PyVar)){ - _all_types[type.index].m__next__ = f; + _all_types[type].m__next__ = f; bind_func(type, __next__, 1, [](VM* vm, ArgsView args){ int n = lambda_get_userdata(args.begin())(vm, args[0]); return vm->__pack_next_retval(n); @@ -1486,7 +1486,7 @@ void VM::bind__next__(Type type, PyVar (*f)(VM*, PyVar)){ #define BIND_UNARY_SPECIAL(name) \ void VM::bind##name(Type type, PyVar (*f)(VM*, PyVar)){ \ - _all_types[type.index].m##name = f; \ + _all_types[type].m##name = f; \ bind_func(type, name, 1, [](VM* vm, ArgsView args){ \ return lambda_get_userdata(args.begin())(vm, args[0]);\ }, f); \ @@ -1497,7 +1497,7 @@ void VM::bind__next__(Type type, PyVar (*f)(VM*, PyVar)){ #undef BIND_UNARY_SPECIAL void VM::bind__str__(Type type, Str (*f)(VM*, PyVar)){ - _all_types[type.index].m__str__ = f; + _all_types[type].m__str__ = f; bind_func(type, __str__, 1, [](VM* vm, ArgsView args){ Str s = lambda_get_userdata(args.begin())(vm, args[0]); 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)){ - _all_types[type.index].m__repr__ = f; + _all_types[type].m__repr__ = f; bind_func(type, __repr__, 1, [](VM* vm, ArgsView args){ Str s = lambda_get_userdata(args.begin())(vm, args[0]); 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)){ - _all_types[type.index].m__hash__ = f; + _all_types[type].m__hash__ = f; bind_func(type, __hash__, 1, [](VM* vm, ArgsView args){ i64 ret = lambda_get_userdata(args.begin())(vm, args[0]); 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)){ - _all_types[type.index].m__len__ = f; + _all_types[type].m__len__ = f; bind_func(type, __len__, 1, [](VM* vm, ArgsView args){ i64 ret = lambda_get_userdata(args.begin())(vm, args[0]); return VAR(ret); @@ -1531,7 +1531,7 @@ void VM::bind__len__(Type type, i64 (*f)(VM*, PyVar)){ #define BIND_BINARY_SPECIAL(name) \ void VM::bind##name(Type type, BinaryFuncC f){ \ - _all_types[type.index].m##name = f; \ + _all_types[type].m##name = f; \ bind_func(type, name, 2, [](VM* vm, ArgsView args){ \ return lambda_get_userdata(args.begin())(vm, args[0], args[1]);\ }, f); \