blueloveTH il y a 3 ans
Parent
commit
af945293cd
3 fichiers modifiés avec 20 ajouts et 13 suppressions
  1. 4 1
      src/obj.h
  2. 7 2
      src/pocketpy.h
  3. 9 10
      src/vm.h

+ 4 - 1
src/obj.h

@@ -142,4 +142,7 @@ union __8B {
     f64 _float;
     __8B(i64 val) : _int(val) {}
     __8B(f64 val) : _float(val) {}
-};
+};
+
+const i64 kMinSafeInt = -((i64)1 << 62);
+const i64 kMaxSafeInt = ((i64)1 << 62) - 1;

+ 7 - 2
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)");

+ 9 - 10
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<int*>(bits._int));
+        i64 bits = __8B(value)._int;
+        bits = (bits >> 2) << 2;
+        bits |= 0b10;
+        return PyVar(reinterpret_cast<int*>(bits));
     }
 
     inline f64 PyFloat_AS_C(const PyVar& obj){
         check_type(obj, tp_float);
-        i64 _int = obj.cast<i64>();
-        return __8B(_int & 0b00)._float;
+        i64 bits = obj.cast<i64>();
+        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);