summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/obj.h2
-rw-r--r--py/runtime.c17
-rw-r--r--tests/basics/tests/int-small.py26
3 files changed, 33 insertions, 12 deletions
diff --git a/py/obj.h b/py/obj.h
index b92f1e2a7e..5a104d703c 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -34,6 +34,8 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
// - xxxx...xx10: a qstr, bits 2 and above are the value
// - xxxx...xx00: a pointer to an mp_obj_base_t
+// In SMALL_INT, next-to-highest bits is used as sign, so both must match for value in range
+#define MP_OBJ_FITS_SMALL_INT(n) ((((n) ^ ((n) << 1)) & WORD_MSBIT_HIGH) == 0)
#define MP_OBJ_IS_SMALL_INT(o) ((((mp_small_int_t)(o)) & 1) != 0)
#define MP_OBJ_IS_QSTR(o) ((((mp_small_int_t)(o)) & 3) == 2)
#define MP_OBJ_IS_OBJ(o) ((((mp_small_int_t)(o)) & 3) == 0)
diff --git a/py/runtime.c b/py/runtime.c
index 8d3e900286..2af86b6abd 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -268,10 +268,6 @@ void rt_assign_inline_asm_code(int unique_code_id, void *fun, uint len, int n_ar
#endif
}
-static bool fit_small_int(mp_small_int_t o) {
- return true;
-}
-
int rt_is_true(mp_obj_t arg) {
DEBUG_OP_printf("is true %p\n", arg);
if (MP_OBJ_IS_SMALL_INT(arg)) {
@@ -436,13 +432,10 @@ mp_obj_t rt_unary_op(int op, mp_obj_t arg) {
case RT_UNARY_OP_INVERT: val = ~val; break;
default: assert(0); val = 0;
}
- if (fit_small_int(val)) {
+ if (MP_OBJ_FITS_SMALL_INT(val)) {
return MP_OBJ_NEW_SMALL_INT(val);
- } else {
- // TODO make a bignum
- assert(0);
- return mp_const_none;
}
+ return mp_obj_new_int(val);
} else { // will be an object (small ints are caught in previous if)
mp_obj_base_t *o = arg;
if (o->type->unary_op != NULL) {
@@ -551,11 +544,11 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
default: assert(0);
}
- if (fit_small_int(lhs_val)) {
+ // TODO: We just should make mp_obj_new_int() inline and use that
+ if (MP_OBJ_FITS_SMALL_INT(lhs_val)) {
return MP_OBJ_NEW_SMALL_INT(lhs_val);
}
- // TODO: return long int
- assert(0);
+ return mp_obj_new_int(lhs_val);
} else if (MP_OBJ_IS_TYPE(rhs, &float_type)) {
return mp_obj_float_binary_op(op, lhs_val, rhs);
} else if (MP_OBJ_IS_TYPE(rhs, &complex_type)) {
diff --git a/tests/basics/tests/int-small.py b/tests/basics/tests/int-small.py
new file mode 100644
index 0000000000..be338c4a4c
--- /dev/null
+++ b/tests/basics/tests/int-small.py
@@ -0,0 +1,26 @@
+# This test small int range for 32-bit machine
+
+a = 0x3fffff
+print(a)
+a *= 0x10
+print(a)
+a *= 0x10
+print(a)
+a += 0xff
+print(a)
+# This would overflow
+#a += 1
+
+a = -0x3fffff
+print(a)
+a *= 0x10
+print(a)
+a *= 0x10
+print(a)
+a -= 0xff
+print(a)
+# This still doesn't overflow
+a -= 1
+print(a)
+# This would overflow
+#a -= 1