diff --git a/3rd/cjson/src/cJSONw.cpp b/3rd/cjson/src/cJSONw.cpp index cef69b79..5711f1d7 100644 --- a/3rd/cjson/src/cJSONw.cpp +++ b/3rd/cjson/src/cJSONw.cpp @@ -24,7 +24,7 @@ static cJSON* covert_dict_to_cjson(const Dict& dict, VM* vm){ } static cJSON* convert_python_object_to_cjson(PyVar obj, VM* vm){ - if(obj == vm->None) return cJSON_CreateNull(); + if(is_none(obj)) return cJSON_CreateNull(); Type obj_t = vm->_tp(obj); switch(obj_t){ case VM::tp_int.index: cJSON_CreateNumber(_CAST(i64, obj)); diff --git a/3rd/lua_bridge/src/lua_bridge.cpp b/3rd/lua_bridge/src/lua_bridge.cpp index 5a00aab3..17c92e6c 100644 --- a/3rd/lua_bridge/src/lua_bridge.cpp +++ b/3rd/lua_bridge/src/lua_bridge.cpp @@ -217,7 +217,7 @@ struct PyLuaFunction: PyLuaObject{ }; void lua_push_from_python(VM* vm, PyVar val){ - if(val == vm->None){ + if(is_none(val)){ lua_pushnil(_L); return; } diff --git a/include/pocketpy/interpreter/cffi.hpp b/include/pocketpy/interpreter/cffi.hpp index 0c4627f5..604e58d1 100644 --- a/include/pocketpy/interpreter/cffi.hpp +++ b/include/pocketpy/interpreter/cffi.hpp @@ -94,7 +94,7 @@ struct Struct { template Tp to_void_p(VM* vm, PyVar var) { static_assert(std::is_pointer_v); - if(var == vm->None) return nullptr; // None can be casted to any pointer implicitly + if(is_none(var)) return nullptr; // None can be casted to any pointer implicitly VoidP& p = CAST(VoidP&, var); return reinterpret_cast(p.ptr); } diff --git a/include/pocketpy/interpreter/vm.hpp b/include/pocketpy/interpreter/vm.hpp index 25c8530d..5a508e68 100644 --- a/include/pocketpy/interpreter/vm.hpp +++ b/include/pocketpy/interpreter/vm.hpp @@ -218,13 +218,14 @@ public: constexpr static Type tp_super = Type(15), tp_exception = Type(16), tp_bytes = Type(17), tp_mappingproxy = Type(18); constexpr static Type tp_dict = Type(19), tp_property = Type(20), tp_star_wrapper = Type(21); constexpr static Type tp_staticmethod = Type(22), tp_classmethod = Type(23); - constexpr static Type tp_none_type = Type(24), tp_not_implemented = Type(25), tp_ellipsis = Type(26); + constexpr static Type tp_none_type = Type(kTpNoneTypeIndex), tp_not_implemented_type = Type(kTpNotImplementedTypeIndex); + constexpr static Type tp_ellipsis = Type(26); constexpr static Type tp_stack_memory = Type(kTpStackMemoryIndex); constexpr static PyVar True{const_sso_var(), tp_bool, 1}; constexpr static PyVar False{const_sso_var(), tp_bool, 0}; constexpr static PyVar None{const_sso_var(), tp_none_type, 0}; - constexpr static PyVar NotImplemented{const_sso_var(), tp_not_implemented, 0}; + constexpr static PyVar NotImplemented{const_sso_var(), tp_not_implemented_type, 0}; constexpr static PyVar Ellipsis{const_sso_var(), tp_ellipsis, 0}; const bool enable_os; @@ -421,9 +422,6 @@ public: const PyTypeInfo* _tp_info(Type type) { return &_all_types[type]; } PyObject* _t(PyVar obj){ return _all_types[_tp(obj)].obj; } PyObject* _t(Type type){ return _all_types[type].obj; } - - // equivalent to `obj == NotImplemented` but faster - static bool is_not_implemented(PyVar obj){ return obj.type == tp_not_implemented; } #endif #if PK_REGION("User Type Registration") @@ -684,7 +682,7 @@ __T _py_cast__internal(VM* vm, PyVar obj) { if constexpr(std::is_same_v || std::is_same_v) { static_assert(!std::is_reference_v<__T>); // str (shortcuts) - if(obj == vm->None) return nullptr; + if(is_none(obj)) return nullptr; if constexpr(with_check) vm->check_type(obj, vm->tp_str); return PK_OBJ_GET(Str, obj).c_str(); } else if constexpr(std::is_same_v) { diff --git a/include/pocketpy/objects/builtins.hpp b/include/pocketpy/objects/builtins.hpp index 49cfc8a1..d1d84113 100644 --- a/include/pocketpy/objects/builtins.hpp +++ b/include/pocketpy/objects/builtins.hpp @@ -75,8 +75,10 @@ struct Slice { void _gc_mark(VM*) const; }; -const inline int kTpIntIndex = 3; -const inline int kTpFloatIndex = 4; +const inline int16_t kTpIntIndex = 3; +const inline int16_t kTpFloatIndex = 4; +const inline int16_t kTpNoneTypeIndex = 24; +const inline int16_t kTpNotImplementedTypeIndex = 25; inline bool is_tagged(PyVar p) noexcept { return !p.is_ptr; } @@ -84,6 +86,10 @@ inline bool is_float(PyVar p) noexcept { return p.type.index == kTpFloatIndex; } inline bool is_int(PyVar p) noexcept { return p.type.index == kTpIntIndex; } +inline bool is_none(PyVar p) noexcept { return p.type.index == kTpNoneTypeIndex; } + +inline bool is_not_implemented(PyVar p) noexcept { return p.type.index == kTpNotImplementedTypeIndex; } + inline bool is_type(PyVar obj, Type type) { assert(obj != nullptr); return obj.type == type; diff --git a/src/interpreter/ceval.cpp b/src/interpreter/ceval.cpp index 1899efc1..9a7b7ac3 100644 --- a/src/interpreter/ceval.cpp +++ b/src/interpreter/ceval.cpp @@ -1042,7 +1042,7 @@ PyVar VM::__run_top_frame() { case OP_BEGIN_CLASS: { StrName _name(byte.arg); PyVar _0 = POPX(); // super - if(_0 == None) _0 = _t(tp_object); + 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); } diff --git a/src/interpreter/vm.cpp b/src/interpreter/vm.cpp index 1c0b452d..243a20c8 100644 --- a/src/interpreter/vm.cpp +++ b/src/interpreter/vm.cpp @@ -46,7 +46,7 @@ struct JsonSerializer { void write_object(PyVar obj) { Type obj_t = vm->_tp(obj); - if(obj == vm->None) { + if(is_none(obj)) { ss << "null"; } else if(obj_t == vm->tp_int) { ss << _CAST(i64, obj); @@ -285,7 +285,7 @@ bool VM::py_callable(PyVar obj) { PyVar VM::__minmax_reduce(bool (VM::*op)(PyVar, PyVar), PyVar args, PyVar key) { auto _lock = heap.gc_scope_lock(); const Tuple& args_tuple = PK_OBJ_GET(Tuple, args); // from *args, it must be a tuple - if(key == vm->None && args_tuple.size() == 2) { + if(is_none(key) && args_tuple.size() == 2) { // fast path PyVar a = args_tuple[0]; PyVar b = args_tuple[1]; @@ -304,7 +304,7 @@ PyVar VM::__minmax_reduce(bool (VM::*op)(PyVar, PyVar), PyVar args, PyVar key) { if(view.empty()) ValueError("arg is an empty sequence"); PyVar res = view[0]; - if(key == vm->None) { + if(is_none(key)) { for(int i = 1; i < view.size(); i++) { if((this->*op)(view[i], res)) res = view[i]; } @@ -419,7 +419,7 @@ PyVar VM::py_negate(PyVar obj) { } bool VM::__py_bool_non_trivial(PyVar obj) { - if(obj == None) return false; + if(is_none(obj)) return false; if(is_int(obj)) return _CAST(i64, obj) != 0; if(is_float(obj)) return _CAST(f64, obj) != 0.0; PyVar self; @@ -486,20 +486,20 @@ void VM::parse_int_slice(const Slice& s, int length, int& start, int& stop, int& if(value > max) return max; return value; }; - if(s.step == None) + if(is_none(s.step)) step = 1; else step = CAST(int, s.step); if(step == 0) ValueError("slice step cannot be zero"); if(step > 0) { - if(s.start == None) { + if(is_none(s.start)) { start = 0; } else { start = CAST(int, s.start); if(start < 0) start += length; start = clip(start, 0, length); } - if(s.stop == None) { + if(is_none(s.stop)) { stop = length; } else { stop = CAST(int, s.stop); @@ -507,14 +507,14 @@ void VM::parse_int_slice(const Slice& s, int length, int& start, int& stop, int& stop = clip(stop, 0, length); } } else { - if(s.start == None) { + if(is_none(s.start)) { start = length - 1; } else { start = CAST(int, s.start); if(start < 0) start += length; start = clip(start, -1, length - 1); } - if(s.stop == None) { + if(is_none(s.stop)) { stop = -1; } else { stop = CAST(int, s.stop); @@ -557,7 +557,7 @@ PyVar VM::__py_exec_internal(const CodeObject_& code, PyVar globals, PyVar local if(!callstack.empty()) frame = &callstack.top(); // fast path - if(frame && globals == vm->None && locals == vm->None) { + if(frame && is_none(globals) && is_none(locals)) { return vm->_exec(code.get(), frame->_module, frame->_callable, frame->_locals); } @@ -569,8 +569,8 @@ PyVar VM::__py_exec_internal(const CodeObject_& code, PyVar globals, PyVar local NameDict_ locals_closure = nullptr; Dict* locals_dict = nullptr; - if(frame && globals == vm->None) { - globals_obj = frame->_module; + if(is_none(globals)){ + globals_obj = frame ? frame->_module: _main; } else { if(is_type(globals, VM::tp_mappingproxy)) { globals_obj = PK_OBJ_GET(MappingProxy, globals).obj; @@ -588,7 +588,7 @@ PyVar VM::__py_exec_internal(const CodeObject_& code, PyVar globals, PyVar local PyVar retval = nullptr; - if(locals == vm->None) { + if(is_none(locals)) { retval = vm->_exec(code, globals_obj); // only globals } else { check_compatible_type(locals, VM::tp_dict); @@ -909,7 +909,7 @@ void VM::__init_builtin_types() { validate(tp_classmethod, new_type_object(nullptr, "classmethod", tp_object, false)); validate(tp_none_type, new_type_object(nullptr, "NoneType", tp_object, false)); - validate(tp_not_implemented, new_type_object(nullptr, "NotImplementedType", tp_object, false)); + validate(tp_not_implemented_type, new_type_object(nullptr, "NotImplementedType", tp_object, false)); validate(tp_ellipsis, new_type_object(nullptr, "ellipsis", tp_object, false)); validate(tp_stack_memory, new_type_object(nullptr, "_stack_memory", tp_object, false)); diff --git a/src/modules/array2d.cpp b/src/modules/array2d.cpp index ad05171c..efe8ffd8 100644 --- a/src/modules/array2d.cpp +++ b/src/modules/array2d.cpp @@ -154,7 +154,7 @@ struct Array2d { case VM::tp_float.index: is_basic_type = true; break; case VM::tp_str.index: is_basic_type = true; break; case VM::tp_bool.index: is_basic_type = true; break; - default: is_basic_type = _2 == vm->None; + default: is_basic_type = is_none(_2); } if(is_basic_type) { diff --git a/src/modules/linalg.cpp b/src/modules/linalg.cpp index 2051b5d8..3b1cb77b 100644 --- a/src/modules/linalg.cpp +++ b/src/modules/linalg.cpp @@ -396,7 +396,7 @@ void Mat3x3::_register(VM* vm, PyObject* mod, PyObject* type) { vm->bind(type, "matmul(self, other: mat3x3, out: mat3x3 = None)", [](VM* vm, ArgsView args) { const Mat3x3& self = _CAST(Mat3x3&, args[0]); const Mat3x3& other = CAST(Mat3x3&, args[1]); - if(args[2] == vm->None) { + if(is_none(args[2])) { return vm->new_user_object(self.matmul(other)); } else { Mat3x3& out = CAST(Mat3x3&, args[2]); diff --git a/src/modules/random.cpp b/src/modules/random.cpp index 5ca8da7a..6dca0d54 100644 --- a/src/modules/random.cpp +++ b/src/modules/random.cpp @@ -183,7 +183,7 @@ struct Random { int size = view.size(); if(size == 0) vm->IndexError("cannot choose from an empty sequence"); array cum_weights(size); - if(args[2] == vm->None) { + if(is_none(args[2])) { for(int i = 0; i < size; i++) cum_weights[i] = i + 1; } else { diff --git a/src/pocketpy.cpp b/src/pocketpy.cpp index 2541aa85..908689a2 100644 --- a/src/pocketpy.cpp +++ b/src/pocketpy.cpp @@ -162,7 +162,7 @@ void __init_builtins(VM* _vm) { if(is_int(args[0])) return args[0]; f64 x = CAST(f64, args[0]); f64 offset = x >= 0 ? 0.5 : -0.5; - if(args[1] == vm->None) return VAR((i64)(x + offset)); + if(is_none(args[1])) return VAR((i64)(x + offset)); int ndigits = CAST(int, args[1]); if(ndigits < 0) vm->ValueError("ndigits should be non-negative"); // ndigits > 0 @@ -751,7 +751,7 @@ void __init_builtins(VM* _vm) { _vm->bind(_vm->_t(VM::tp_str), "strip(self, chars=None)", [](VM* vm, ArgsView args) { const Str& self = _CAST(Str&, args[0]); - if(args[1] == vm->None) { + if(is_none(args[1])) { return VAR(self.strip()); } else { const Str& chars = CAST(Str&, args[1]); @@ -761,7 +761,7 @@ void __init_builtins(VM* _vm) { _vm->bind(_vm->_t(VM::tp_str), "lstrip(self, chars=None)", [](VM* vm, ArgsView args) { const Str& self = _CAST(Str&, args[0]); - if(args[1] == vm->None) { + if(is_none(args[1])) { return VAR(self.lstrip()); } else { const Str& chars = CAST(Str&, args[1]); @@ -771,7 +771,7 @@ void __init_builtins(VM* _vm) { _vm->bind(_vm->_t(VM::tp_str), "rstrip(self, chars=None)", [](VM* vm, ArgsView args) { const Str& self = _CAST(Str&, args[0]); - if(args[1] == vm->None) { + if(is_none(args[1])) { return VAR(self.rstrip()); } else { const Str& chars = CAST(Str&, args[1]); @@ -826,7 +826,7 @@ void __init_builtins(VM* _vm) { _vm->bind(_vm->_t(VM::tp_list), "sort(self, key=None, reverse=False)", [](VM* vm, ArgsView args) { List& self = _CAST(List&, args[0]); PyVar key = args[1]; - if(key == vm->None) { + if(is_none(key)) { std::stable_sort(self.begin(), self.end(), [vm](PyVar a, PyVar b) { return vm->py_lt(a, b); }); diff --git a/src/pocketpy_c.cpp b/src/pocketpy_c.cpp index a9a4c3c0..60870d91 100644 --- a/src/pocketpy_c.cpp +++ b/src/pocketpy_c.cpp @@ -294,7 +294,7 @@ bool pkpy_is_none(pkpy_vm* vm_handle, int i) { PK_ASSERT_NO_ERROR() PK_PROTECTED( PyVar item = stack_item(vm, i); - return item == vm->None; + return is_none(item); ) }