diff --git a/src/obj.h b/src/obj.h index c3f5cb27..9a5ee417 100644 --- a/src/obj.h +++ b/src/obj.h @@ -142,4 +142,7 @@ union __8B { f64 _float; __8B(i64 val) : _int(val) {} __8B(f64 val) : _float(val) {} -}; \ No newline at end of file +}; + +const i64 kMinSafeInt = -((i64)1 << 62); +const i64 kMaxSafeInt = ((i64)1 << 62) - 1; \ No newline at end of file diff --git a/src/pocketpy.h b/src/pocketpy.h index c69bbf2b..26288699 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -20,7 +20,7 @@ CodeObject_ VM::compile(Str source, Str filename, CompileMode mode) { #define BIND_NUM_ARITH_OPT(name, op) \ _vm->_bind_methods<1>({"int","float"}, #name, [](VM* vm, pkpy::Args& args){ \ - if(is_type(args[0], vm->tp_int) && is_type(args[1], vm->tp_int)){ \ + if(is_int(args[0]) && is_int(args[1])){ \ return vm->PyInt(vm->PyInt_AS_C(args[0]) op vm->PyInt_AS_C(args[1])); \ }else{ \ return vm->PyFloat(vm->num_to_float(args[0]) op vm->num_to_float(args[1])); \ @@ -82,9 +82,14 @@ void init_builtins(VM* _vm) { }); _vm->bind_builtin_func<1>("repr", CPP_LAMBDA(vm->asRepr(args[0]))); - _vm->bind_builtin_func<1>("hash", CPP_LAMBDA(vm->PyInt(vm->hash(args[0])))); _vm->bind_builtin_func<1>("len", CPP_LAMBDA(vm->call(args[0], __len__, pkpy::no_arg()))); + _vm->bind_builtin_func<1>("hash", [](VM* vm, pkpy::Args& args){ + i64 value = vm->hash(args[0]); + if(value < kMinSafeInt || value > kMaxSafeInt) value >>= 2; + return vm->PyInt(value); + }); + _vm->bind_builtin_func<1>("chr", [](VM* vm, pkpy::Args& args) { i64 i = vm->PyInt_AS_C(args[0]); if (i < 0 || i > 128) vm->ValueError("chr() arg not in range(128)"); diff --git a/src/vm.h b/src/vm.h index 9e86ebc3..62cfc67a 100644 --- a/src/vm.h +++ b/src/vm.h @@ -551,9 +551,7 @@ public: } inline PyVar PyInt(i64 value) { - const i64 MIN_SAFE_INT = -((i64)1 << 62); - const i64 MAX_SAFE_INT = ((i64)1 << 62) - 1; - if(value < MIN_SAFE_INT || value > MAX_SAFE_INT){ + if(value < kMinSafeInt || value > kMaxSafeInt){ _error("OverflowError", std::to_string(value) + " is out of range"); } value = (value << 2) | 0b01; @@ -567,16 +565,17 @@ public: } inline PyVar PyFloat(f64 value) { - auto bits = __8B(value); - i64 _int = bits._int; - bits._int = (_int & 0b00) | 0b10; - return PyVar(reinterpret_cast(bits._int)); + i64 bits = __8B(value)._int; + bits = (bits >> 2) << 2; + bits |= 0b10; + return PyVar(reinterpret_cast(bits)); } inline f64 PyFloat_AS_C(const PyVar& obj){ check_type(obj, tp_float); - i64 _int = obj.cast(); - return __8B(_int & 0b00)._float; + i64 bits = obj.cast(); + bits = (bits >> 2) << 2; + return __8B(bits)._float; } DEF_NATIVE(List, pkpy::List, tp_list) @@ -647,7 +646,7 @@ public: i64 hash(const PyVar& obj){ if (is_type(obj, tp_str)) return PyStr_AS_C(obj).hash(); - if (is_int(obj)) return PyInt_AS_C(obj); + if (is_int(obj)) return PyInt_AS_C(obj); if (is_type(obj, tp_tuple)) { i64 x = 1000003; const pkpy::Tuple& items = PyTuple_AS_C(obj);