This commit is contained in:
blueloveTH 2023-02-27 23:45:16 +08:00
parent 6a82644f9a
commit b0e2c6e489
5 changed files with 42 additions and 50 deletions

View File

@ -150,13 +150,13 @@ PyVar VM::run_frame(Frame* frame){
PyVar rhs = frame->pop_value(this); PyVar rhs = frame->pop_value(this);
bool ret_c = rhs == frame->top_value(this); bool ret_c = rhs == frame->top_value(this);
if(byte.arg == 1) ret_c = !ret_c; if(byte.arg == 1) ret_c = !ret_c;
frame->top() = PyBool(ret_c); frame->top() = py_object(this, ret_c);
} continue; } continue;
case OP_CONTAINS_OP: { case OP_CONTAINS_OP: {
PyVar rhs = frame->pop_value(this); PyVar rhs = frame->pop_value(this);
bool ret_c = PyBool_AS_C(call(rhs, __contains__, one_arg(frame->pop_value(this)))); bool ret_c = py_cast_v<bool>(this, call(rhs, __contains__, one_arg(frame->pop_value(this))));
if(byte.arg == 1) ret_c = !ret_c; if(byte.arg == 1) ret_c = !ret_c;
frame->push(PyBool(ret_c)); frame->push(py_object(this, ret_c));
} continue; } continue;
case OP_UNARY_NEGATIVE: case OP_UNARY_NEGATIVE:
frame->top() = num_negated(frame->top_value(this)); frame->top() = num_negated(frame->top_value(this));
@ -164,10 +164,10 @@ PyVar VM::run_frame(Frame* frame){
case OP_UNARY_NOT: { case OP_UNARY_NOT: {
PyVar obj = frame->pop_value(this); PyVar obj = frame->pop_value(this);
const PyVar& obj_bool = asBool(obj); const PyVar& obj_bool = asBool(obj);
frame->push(PyBool(!_PyBool_AS_C(obj_bool))); frame->push(py_object(this, !_py_cast_v<bool>(this, obj_bool)));
} continue; } continue;
case OP_POP_JUMP_IF_FALSE: case OP_POP_JUMP_IF_FALSE:
if(!_PyBool_AS_C(asBool(frame->pop_value(this)))) frame->jump_abs(byte.arg); if(!_py_cast_v<bool>(this, asBool(frame->pop_value(this)))) frame->jump_abs(byte.arg);
continue; continue;
case OP_LOAD_NONE: frame->push(None); continue; case OP_LOAD_NONE: frame->push(None); continue;
case OP_LOAD_TRUE: frame->push(True); continue; case OP_LOAD_TRUE: frame->push(True); continue;
@ -182,7 +182,7 @@ PyVar VM::run_frame(Frame* frame){
case OP_EXCEPTION_MATCH: { case OP_EXCEPTION_MATCH: {
const auto& e = py_cast<Exception>(this, frame->top()); const auto& e = py_cast<Exception>(this, frame->top());
StrName name = frame->co->names[byte.arg].first; StrName name = frame->co->names[byte.arg].first;
frame->push(PyBool(e.match_type(name))); frame->push(py_object(this, e.match_type(name)));
} continue; } continue;
case OP_RAISE: { case OP_RAISE: {
PyVar obj = frame->pop_value(this); PyVar obj = frame->pop_value(this);

View File

@ -89,13 +89,13 @@ struct Pointer{
vm->bind_method<1>(type, "__eq__", [](VM* vm, Args& args) { vm->bind_method<1>(type, "__eq__", [](VM* vm, Args& args) {
Pointer& self = vm->_cast<Pointer>(args[0]); Pointer& self = vm->_cast<Pointer>(args[0]);
Pointer& other = vm->_cast<Pointer>(args[1]); Pointer& other = vm->_cast<Pointer>(args[1]);
return vm->PyBool(self.ptr == other.ptr); return py_object(vm, self.ptr == other.ptr);
}); });
vm->bind_method<1>(type, "__ne__", [](VM* vm, Args& args) { vm->bind_method<1>(type, "__ne__", [](VM* vm, Args& args) {
Pointer& self = vm->_cast<Pointer>(args[0]); Pointer& self = vm->_cast<Pointer>(args[0]);
Pointer& other = vm->_cast<Pointer>(args[1]); Pointer& other = vm->_cast<Pointer>(args[1]);
return vm->PyBool(self.ptr != other.ptr); return py_object(vm, self.ptr != other.ptr);
}); });
// https://docs.python.org/zh-cn/3/library/ctypes.html // https://docs.python.org/zh-cn/3/library/ctypes.html
@ -145,7 +145,7 @@ struct Pointer{
case C_TYPE("int_"): return py_object(vm, ref<int>()); case C_TYPE("int_"): return py_object(vm, ref<int>());
case C_TYPE("float_"): return py_object(vm, ref<float>()); case C_TYPE("float_"): return py_object(vm, ref<float>());
case C_TYPE("double_"): return py_object(vm, ref<double>()); case C_TYPE("double_"): return py_object(vm, ref<double>());
case C_TYPE("bool_"): return vm->PyBool(ref<bool>()); case C_TYPE("bool_"): return py_object(vm, ref<bool>());
case C_TYPE("void_"): vm->ValueError("cannot get void*"); break; case C_TYPE("void_"): vm->ValueError("cannot get void*"); break;
case C_TYPE("int8_"): return py_object(vm, ref<int8_t>()); case C_TYPE("int8_"): return py_object(vm, ref<int8_t>());
case C_TYPE("int16_"): return py_object(vm, ref<int16_t>()); case C_TYPE("int16_"): return py_object(vm, ref<int16_t>());
@ -168,7 +168,7 @@ struct Pointer{
case C_TYPE("int_"): ref<int>() = py_cast_v<i64>(vm, val); break; case C_TYPE("int_"): ref<int>() = py_cast_v<i64>(vm, val); break;
case C_TYPE("float_"): ref<float>() = py_cast_v<f64>(vm, val); break; case C_TYPE("float_"): ref<float>() = py_cast_v<f64>(vm, val); break;
case C_TYPE("double_"): ref<double>() = py_cast_v<f64>(vm, val); break; case C_TYPE("double_"): ref<double>() = py_cast_v<f64>(vm, val); break;
case C_TYPE("bool_"): ref<bool>() = vm->PyBool_AS_C(val); break; case C_TYPE("bool_"): ref<bool>() = py_cast_v<bool>(vm, val); break;
case C_TYPE("void_"): vm->ValueError("cannot set void*"); break; case C_TYPE("void_"): vm->ValueError("cannot set void*"); break;
case C_TYPE("int8_"): ref<int8_t>() = py_cast_v<i64>(vm, val); break; case C_TYPE("int8_"): ref<int8_t>() = py_cast_v<i64>(vm, val); break;
case C_TYPE("int16_"): ref<int16_t>() = py_cast_v<i64>(vm, val); break; case C_TYPE("int16_"): ref<int16_t>() = py_cast_v<i64>(vm, val); break;

View File

@ -1101,8 +1101,8 @@ __LISTCOMP:
} }
if(match(TK("@num"))) return parser->prev.value; if(match(TK("@num"))) return parser->prev.value;
if(match(TK("@str"))) return parser->prev.value; if(match(TK("@str"))) return parser->prev.value;
if(match(TK("True"))) return vm->PyBool(true); if(match(TK("True"))) return py_object(vm, true);
if(match(TK("False"))) return vm->PyBool(false); if(match(TK("False"))) return py_object(vm, false);
if(match(TK("None"))) return vm->None; if(match(TK("None"))) return vm->None;
if(match(TK("..."))) return vm->Ellipsis; if(match(TK("..."))) return vm->Ellipsis;
return nullptr; return nullptr;

View File

@ -31,12 +31,12 @@ CodeObject_ VM::compile(Str source, Str filename, CompileMode mode) {
#define BIND_NUM_LOGICAL_OPT(name, op, is_eq) \ #define BIND_NUM_LOGICAL_OPT(name, op, is_eq) \
_vm->_bind_methods<1>({"int","float"}, #name, [](VM* vm, Args& args){ \ _vm->_bind_methods<1>({"int","float"}, #name, [](VM* vm, Args& args){ \
if(!is_both_int_or_float(args[0], args[1])){ \ if(!is_both_int_or_float(args[0], args[1])){ \
if constexpr(is_eq) return vm->PyBool(args[0] op args[1]); \ if constexpr(is_eq) return py_object(vm, args[0] op args[1]); \
vm->TypeError("unsupported operand type(s) for " #op ); \ vm->TypeError("unsupported operand type(s) for " #op ); \
} \ } \
if(is_both_int(args[0], args[1])) \ if(is_both_int(args[0], args[1])) \
return vm->PyBool(_py_cast_v<i64>(vm, args[0]) op _py_cast_v<i64>(vm, args[1])); \ return py_object(vm, _py_cast_v<i64>(vm, args[0]) op _py_cast_v<i64>(vm, args[1])); \
return vm->PyBool(vm->num_to_float(args[0]) op vm->num_to_float(args[1])); \ return py_object(vm, vm->num_to_float(args[0]) op vm->num_to_float(args[1])); \
}); });
@ -117,7 +117,7 @@ void init_builtins(VM* _vm) {
}); });
_vm->bind_builtin_func<2>("hasattr", [](VM* vm, Args& args) { _vm->bind_builtin_func<2>("hasattr", [](VM* vm, Args& args) {
return vm->PyBool(vm->getattr(args[0], py_cast<Str>(vm, args[1]), false) != nullptr); return py_object(vm, vm->getattr(args[0], py_cast<Str>(vm, args[1]), false) != nullptr);
}); });
_vm->bind_builtin_func<3>("setattr", [](VM* vm, Args& args) { _vm->bind_builtin_func<3>("setattr", [](VM* vm, Args& args) {
@ -159,8 +159,8 @@ void init_builtins(VM* _vm) {
return py_object(vm, s); return py_object(vm, s);
}); });
_vm->bind_method<1>("object", "__eq__", CPP_LAMBDA(vm->PyBool(args[0] == args[1]))); _vm->bind_method<1>("object", "__eq__", CPP_LAMBDA(py_object(vm, args[0] == args[1])));
_vm->bind_method<1>("object", "__ne__", CPP_LAMBDA(vm->PyBool(args[0] != args[1]))); _vm->bind_method<1>("object", "__ne__", CPP_LAMBDA(py_object(vm, args[0] != args[1])));
_vm->bind_static_method<1>("type", "__new__", CPP_LAMBDA(vm->_t(args[0]))); _vm->bind_static_method<1>("type", "__new__", CPP_LAMBDA(vm->_t(args[0])));
@ -211,7 +211,7 @@ void init_builtins(VM* _vm) {
_vm->bind_static_method<1>("int", "__new__", [](VM* vm, Args& args) { _vm->bind_static_method<1>("int", "__new__", [](VM* vm, Args& args) {
if (is_type(args[0], vm->tp_int)) return args[0]; if (is_type(args[0], vm->tp_int)) return args[0];
if (is_type(args[0], vm->tp_float)) return py_object(vm, (i64)py_cast_v<f64>(vm, args[0])); if (is_type(args[0], vm->tp_float)) return py_object(vm, (i64)py_cast_v<f64>(vm, args[0]));
if (is_type(args[0], vm->tp_bool)) return py_object(vm, vm->_PyBool_AS_C(args[0]) ? 1 : 0); if (is_type(args[0], vm->tp_bool)) return py_object(vm, _py_cast_v<bool>(vm, args[0]) ? 1 : 0);
if (is_type(args[0], vm->tp_str)) { if (is_type(args[0], vm->tp_str)) {
const Str& s = py_cast<Str>(vm, args[0]); const Str& s = py_cast<Str>(vm, args[0]);
try{ try{
@ -257,7 +257,7 @@ void init_builtins(VM* _vm) {
_vm->bind_static_method<1>("float", "__new__", [](VM* vm, Args& args) { _vm->bind_static_method<1>("float", "__new__", [](VM* vm, Args& args) {
if (is_type(args[0], vm->tp_int)) return py_object(vm, (f64)py_cast_v<i64>(vm, args[0])); if (is_type(args[0], vm->tp_int)) return py_object(vm, (f64)py_cast_v<i64>(vm, args[0]));
if (is_type(args[0], vm->tp_float)) return args[0]; if (is_type(args[0], vm->tp_float)) return args[0];
if (is_type(args[0], vm->tp_bool)) return py_object(vm, vm->_PyBool_AS_C(args[0]) ? 1.0 : 0.0); if (is_type(args[0], vm->tp_bool)) return py_object(vm, _py_cast_v<bool>(vm, args[0]) ? 1.0 : 0.0);
if (is_type(args[0], vm->tp_str)) { if (is_type(args[0], vm->tp_str)) {
const Str& s = py_cast<Str>(vm, args[0]); const Str& s = py_cast<Str>(vm, args[0]);
if(s == "inf") return py_object(vm, INFINITY); if(s == "inf") return py_object(vm, INFINITY);
@ -306,7 +306,7 @@ void init_builtins(VM* _vm) {
_vm->bind_method<1>("str", "__contains__", [](VM* vm, Args& args) { _vm->bind_method<1>("str", "__contains__", [](VM* vm, Args& args) {
const Str& self = py_cast<Str>(vm, args[0]); const Str& self = py_cast<Str>(vm, args[0]);
const Str& other = py_cast<Str>(vm, args[1]); const Str& other = py_cast<Str>(vm, args[1]);
return vm->PyBool(self.find(other) != Str::npos); return py_object(vm, self.find(other) != Str::npos);
}); });
_vm->bind_method<0>("str", "__str__", CPP_LAMBDA(args[0])); _vm->bind_method<0>("str", "__str__", CPP_LAMBDA(args[0]));
@ -324,14 +324,14 @@ void init_builtins(VM* _vm) {
_vm->bind_method<1>("str", "__eq__", [](VM* vm, Args& args) { _vm->bind_method<1>("str", "__eq__", [](VM* vm, Args& args) {
if(is_type(args[0], vm->tp_str) && is_type(args[1], vm->tp_str)) if(is_type(args[0], vm->tp_str) && is_type(args[1], vm->tp_str))
return vm->PyBool(py_cast<Str>(vm, args[0]) == py_cast<Str>(vm, args[1])); return py_object(vm, py_cast<Str>(vm, args[0]) == py_cast<Str>(vm, args[1]));
return vm->PyBool(args[0] == args[1]); return py_object(vm, args[0] == args[1]);
}); });
_vm->bind_method<1>("str", "__ne__", [](VM* vm, Args& args) { _vm->bind_method<1>("str", "__ne__", [](VM* vm, Args& args) {
if(is_type(args[0], vm->tp_str) && is_type(args[1], vm->tp_str)) if(is_type(args[0], vm->tp_str) && is_type(args[1], vm->tp_str))
return vm->PyBool(py_cast<Str>(vm, args[0]) != py_cast<Str>(vm, args[1])); return py_object(vm, py_cast<Str>(vm, args[0]) != py_cast<Str>(vm, args[1]));
return vm->PyBool(args[0] != args[1]); return py_object(vm, args[0] != args[1]);
}); });
_vm->bind_method<1>("str", "__getitem__", [](VM* vm, Args& args) { _vm->bind_method<1>("str", "__getitem__", [](VM* vm, Args& args) {
@ -351,13 +351,13 @@ void init_builtins(VM* _vm) {
_vm->bind_method<1>("str", "__gt__", [](VM* vm, Args& args) { _vm->bind_method<1>("str", "__gt__", [](VM* vm, Args& args) {
const Str& self (py_cast<Str>(vm, args[0])); const Str& self (py_cast<Str>(vm, args[0]));
const Str& obj (py_cast<Str>(vm, args[1])); const Str& obj (py_cast<Str>(vm, args[1]));
return vm->PyBool(self > obj); return py_object(vm, self > obj);
}); });
_vm->bind_method<1>("str", "__lt__", [](VM* vm, Args& args) { _vm->bind_method<1>("str", "__lt__", [](VM* vm, Args& args) {
const Str& self (py_cast<Str>(vm, args[0])); const Str& self (py_cast<Str>(vm, args[0]));
const Str& obj (py_cast<Str>(vm, args[1])); const Str& obj (py_cast<Str>(vm, args[1]));
return vm->PyBool(self < obj); return py_object(vm, self < obj);
}); });
_vm->bind_method<2>("str", "replace", [](VM* vm, Args& args) { _vm->bind_method<2>("str", "replace", [](VM* vm, Args& args) {
@ -377,13 +377,13 @@ void init_builtins(VM* _vm) {
_vm->bind_method<1>("str", "startswith", [](VM* vm, Args& args) { _vm->bind_method<1>("str", "startswith", [](VM* vm, Args& args) {
const Str& _self = py_cast<Str>(vm, args[0]); const Str& _self = py_cast<Str>(vm, args[0]);
const Str& _prefix = py_cast<Str>(vm, args[1]); const Str& _prefix = py_cast<Str>(vm, args[1]);
return vm->PyBool(_self.find(_prefix) == 0); return py_object(vm, _self.find(_prefix) == 0);
}); });
_vm->bind_method<1>("str", "endswith", [](VM* vm, Args& args) { _vm->bind_method<1>("str", "endswith", [](VM* vm, Args& args) {
const Str& _self = py_cast<Str>(vm, args[0]); const Str& _self = py_cast<Str>(vm, args[0]);
const Str& _suffix = py_cast<Str>(vm, args[1]); const Str& _suffix = py_cast<Str>(vm, args[1]);
return vm->PyBool(_self.rfind(_suffix) == _self.length() - _suffix.length()); return py_object(vm, _self.rfind(_suffix) == _self.length() - _suffix.length());
}); });
_vm->bind_method<1>("str", "join", [](VM* vm, Args& args) { _vm->bind_method<1>("str", "join", [](VM* vm, Args& args) {
@ -521,19 +521,19 @@ void init_builtins(VM* _vm) {
_vm->bind_static_method<1>("bool", "__new__", CPP_LAMBDA(vm->asBool(args[0]))); _vm->bind_static_method<1>("bool", "__new__", CPP_LAMBDA(vm->asBool(args[0])));
_vm->bind_method<0>("bool", "__repr__", [](VM* vm, Args& args) { _vm->bind_method<0>("bool", "__repr__", [](VM* vm, Args& args) {
bool val = vm->PyBool_AS_C(args[0]); bool val = py_cast_v<bool>(vm, args[0]);
return py_object(vm, val ? "True" : "False"); return py_object(vm, val ? "True" : "False");
}); });
_vm->bind_method<0>("bool", "__json__", [](VM* vm, Args& args) { _vm->bind_method<0>("bool", "__json__", [](VM* vm, Args& args) {
bool val = vm->PyBool_AS_C(args[0]); bool val = py_cast_v<bool>(vm, args[0]);
return py_object(vm, val ? "true" : "false"); return py_object(vm, val ? "true" : "false");
}); });
_vm->bind_method<1>("bool", "__xor__", [](VM* vm, Args& args) { _vm->bind_method<1>("bool", "__xor__", [](VM* vm, Args& args) {
bool self = vm->PyBool_AS_C(args[0]); bool self = py_cast_v<bool>(vm, args[0]);
bool other = vm->PyBool_AS_C(args[1]); bool other = py_cast_v<bool>(vm, args[1]);
return vm->PyBool(self ^ other); return py_object(vm, self ^ other);
}); });
_vm->bind_method<0>("ellipsis", "__repr__", CPP_LAMBDA(py_object(vm, "Ellipsis"))); _vm->bind_method<0>("ellipsis", "__repr__", CPP_LAMBDA(py_object(vm, "Ellipsis")));
@ -596,8 +596,8 @@ void add_module_math(VM* vm){
vm->bind_func<1>(mod, "sin", CPP_LAMBDA(py_object(vm, std::sin(vm->num_to_float(args[0]))))); vm->bind_func<1>(mod, "sin", CPP_LAMBDA(py_object(vm, std::sin(vm->num_to_float(args[0])))));
vm->bind_func<1>(mod, "cos", CPP_LAMBDA(py_object(vm, std::cos(vm->num_to_float(args[0]))))); vm->bind_func<1>(mod, "cos", CPP_LAMBDA(py_object(vm, std::cos(vm->num_to_float(args[0])))));
vm->bind_func<1>(mod, "tan", CPP_LAMBDA(py_object(vm, std::tan(vm->num_to_float(args[0]))))); vm->bind_func<1>(mod, "tan", CPP_LAMBDA(py_object(vm, std::tan(vm->num_to_float(args[0])))));
vm->bind_func<1>(mod, "isnan", CPP_LAMBDA(vm->PyBool(std::isnan(vm->num_to_float(args[0]))))); vm->bind_func<1>(mod, "isnan", CPP_LAMBDA(py_object(vm, std::isnan(vm->num_to_float(args[0])))));
vm->bind_func<1>(mod, "isinf", CPP_LAMBDA(vm->PyBool(std::isinf(vm->num_to_float(args[0]))))); vm->bind_func<1>(mod, "isinf", CPP_LAMBDA(py_object(vm, std::isinf(vm->num_to_float(args[0])))));
vm->bind_func<1>(mod, "fabs", CPP_LAMBDA(py_object(vm, std::fabs(vm->num_to_float(args[0]))))); vm->bind_func<1>(mod, "fabs", CPP_LAMBDA(py_object(vm, std::fabs(vm->num_to_float(args[0])))));
vm->bind_func<1>(mod, "floor", CPP_LAMBDA(py_object(vm, (i64)std::floor(vm->num_to_float(args[0]))))); vm->bind_func<1>(mod, "floor", CPP_LAMBDA(py_object(vm, (i64)std::floor(vm->num_to_float(args[0])))));
vm->bind_func<1>(mod, "ceil", CPP_LAMBDA(py_object(vm, (i64)std::ceil(vm->num_to_float(args[0]))))); vm->bind_func<1>(mod, "ceil", CPP_LAMBDA(py_object(vm, (i64)std::ceil(vm->num_to_float(args[0])))));
@ -977,7 +977,7 @@ extern "C" {
switch(ret_code){ switch(ret_code){
case 'i': return py_object(vm, f_int(packet)); case 'i': return py_object(vm, f_int(packet));
case 'f': return py_object(vm, f_float(packet)); case 'f': return py_object(vm, f_float(packet));
case 'b': return vm->PyBool(f_bool(packet)); case 'b': return py_object(vm, f_bool(packet));
case 's': { case 's': {
char* p = f_str(packet); char* p = f_str(packet);
if(p == nullptr) return vm->None; if(p == nullptr) return vm->None;

View File

@ -247,14 +247,6 @@ public:
return static_cast<BaseIter*>(obj->value()); return static_cast<BaseIter*>(obj->value());
} }
// there is only one True/False, so no need to copy them!
inline bool PyBool_AS_C(const PyVar& obj){
check_type(obj, tp_bool);
return obj == True;
}
inline bool _PyBool_AS_C(const PyVar& obj){ return obj == True; }
inline const PyVar& PyBool(bool value){return value ? True : False;}
/***** Error Reporter *****/ /***** Error Reporter *****/
void _error(StrName name, const Str& msg){ void _error(StrName name, const Str& msg){
_error(Exception(name, msg)); _error(Exception(name, msg));
@ -433,7 +425,7 @@ template<> f64 _py_cast_v<f64>(VM* vm, const PyVar& obj){
return __8B(bits)._float; return __8B(bits)._float;
} }
PyVar py_object(VM* vm, bool val){ const PyVar& py_object(VM* vm, bool val){
return val ? vm->True : vm->False; return val ? vm->True : vm->False;
} }
template<> bool py_cast_v<bool>(VM* vm, const PyVar& obj){ template<> bool py_cast_v<bool>(VM* vm, const PyVar& obj){
@ -471,12 +463,12 @@ f64 VM::num_to_float(const PyVar& obj){
const PyVar& VM::asBool(const PyVar& obj){ const PyVar& VM::asBool(const PyVar& obj){
if(is_type(obj, tp_bool)) return obj; if(is_type(obj, tp_bool)) return obj;
if(obj == None) return False; if(obj == None) return False;
if(is_type(obj, tp_int)) return PyBool(py_cast_v<i64>(this, obj) != 0); if(is_type(obj, tp_int)) return py_object(this, py_cast_v<i64>(this, obj) != 0);
if(is_type(obj, tp_float)) return PyBool(py_cast_v<f64>(this, obj) != 0.0); if(is_type(obj, tp_float)) return py_object(this, py_cast_v<f64>(this, obj) != 0.0);
PyVarOrNull len_fn = getattr(obj, __len__, false); PyVarOrNull len_fn = getattr(obj, __len__, false);
if(len_fn != nullptr){ if(len_fn != nullptr){
PyVar ret = call(len_fn); PyVar ret = call(len_fn);
return PyBool(py_cast_v<i64>(this, ret) > 0); return py_object(this, py_cast_v<i64>(this, ret) > 0);
} }
return True; return True;
} }
@ -494,7 +486,7 @@ i64 VM::hash(const PyVar& obj){
return x; return x;
} }
if (is_type(obj, tp_type)) return obj.bits; if (is_type(obj, tp_type)) return obj.bits;
if (is_type(obj, tp_bool)) return _PyBool_AS_C(obj) ? 1 : 0; if (is_type(obj, tp_bool)) return _py_cast_v<bool>(this, obj) ? 1 : 0;
if (is_float(obj)){ if (is_float(obj)){
f64 val = py_cast_v<f64>(this, obj); f64 val = py_cast_v<f64>(this, obj);
return (i64)std::hash<f64>()(val); return (i64)std::hash<f64>()(val);