summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2023-05-25 10:57:08 +1000
committerDamien George <damien@micropython.org>2023-06-01 13:01:07 +1000
commit48ffd6596e7a4c185a81be233b46d3c99a83a7ac (patch)
tree3a15993f388746d0125b875c621a8508b5c8b731 /py
parent3ae78e803b69c4f1fd5dfe7eb732de7075f12e6c (diff)
py: Change MP_UNARY_OP_INT to MP_UNARY_OP_INT_MAYBE.
To be consistent with MP_UNARY_OP_INT_FLOAT and MP_UNARY_OP_INT_COMPLEX, and allow int() to first check if a type supports __int__ before trying other things (as per CPython). Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'py')
-rw-r--r--py/obj.c15
-rw-r--r--py/objint.c11
-rw-r--r--py/objint_longlong.c2
-rw-r--r--py/objint_mpz.c2
-rw-r--r--py/objtype.c4
-rw-r--r--py/runtime.c39
-rw-r--r--py/runtime.h1
-rw-r--r--py/runtime0.h2
8 files changed, 38 insertions, 38 deletions
diff --git a/py/obj.c b/py/obj.c
index 7e26d4c7f..dc6919467 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -298,18 +298,11 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) {
// This function essentially performs implicit type conversion to int
// Note that Python does NOT provide implicit type conversion from
// float to int in the core expression language, try some_list[1.0].
- if (arg == mp_const_false) {
- return 0;
- } else if (arg == mp_const_true) {
- return 1;
- } else if (mp_obj_is_small_int(arg)) {
- return MP_OBJ_SMALL_INT_VALUE(arg);
- } else if (mp_obj_is_exact_type(arg, &mp_type_int)) {
- return mp_obj_int_get_checked(arg);
- } else {
- mp_obj_t res = mp_unary_op(MP_UNARY_OP_INT, (mp_obj_t)arg);
- return mp_obj_int_get_checked(res);
+ mp_int_t val;
+ if (!mp_obj_get_int_maybe(arg, &val)) {
+ mp_raise_TypeError_int_conversion(arg);
}
+ return val;
}
mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg) {
diff --git a/py/objint.c b/py/objint.c
index 1a3ad8694..e54cdb89b 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -48,10 +48,10 @@ STATIC mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args,
case 0:
return MP_OBJ_NEW_SMALL_INT(0);
- case 1:
- if (mp_obj_is_int(args[0])) {
- // already an int (small or long), just return it
- return args[0];
+ case 1: {
+ mp_obj_t o = mp_unary_op(MP_UNARY_OP_INT_MAYBE, args[0]);
+ if (o != MP_OBJ_NULL) {
+ return o;
} else if (mp_obj_is_str_or_bytes(args[0])) {
// a string, parse it
size_t l;
@@ -62,8 +62,9 @@ STATIC mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args,
return mp_obj_new_int_from_float(mp_obj_float_get(args[0]));
#endif
} else {
- return mp_unary_op(MP_UNARY_OP_INT, args[0]);
+ mp_raise_TypeError_int_conversion(args[0]);
}
+ }
case 2:
default: {
diff --git a/py/objint_longlong.c b/py/objint_longlong.c
index 1c0758836..ee499e026 100644
--- a/py/objint_longlong.c
+++ b/py/objint_longlong.c
@@ -119,6 +119,8 @@ mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
self->val = -self->val;
return MP_OBJ_FROM_PTR(self);
}
+ case MP_UNARY_OP_INT_MAYBE:
+ return o_in;
default:
return MP_OBJ_NULL; // op not supported
}
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index e9545149f..8078441d6 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -165,6 +165,8 @@ mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
mpz_abs_inpl(&self2->mpz, &self->mpz);
return MP_OBJ_FROM_PTR(self2);
}
+ case MP_UNARY_OP_INT_MAYBE:
+ return o_in;
default:
return MP_OBJ_NULL; // op not supported
}
diff --git a/py/objtype.c b/py/objtype.c
index 04bdf5acd..772f25d74 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -374,7 +374,7 @@ const byte mp_unary_op_method_name[MP_UNARY_OP_NUM_RUNTIME] = {
[MP_UNARY_OP_BOOL] = MP_QSTR___bool__,
[MP_UNARY_OP_LEN] = MP_QSTR___len__,
[MP_UNARY_OP_HASH] = MP_QSTR___hash__,
- [MP_UNARY_OP_INT] = MP_QSTR___int__,
+ [MP_UNARY_OP_INT_MAYBE] = MP_QSTR___int__,
#if MICROPY_PY_ALL_SPECIAL_METHODS
[MP_UNARY_OP_POSITIVE] = MP_QSTR___pos__,
[MP_UNARY_OP_NEGATIVE] = MP_QSTR___neg__,
@@ -432,7 +432,7 @@ STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
// __hash__ must return a small int
val = MP_OBJ_NEW_SMALL_INT(mp_obj_get_int_truncated(val));
break;
- case MP_UNARY_OP_INT:
+ case MP_UNARY_OP_INT_MAYBE:
// Must return int
if (!mp_obj_is_int(val)) {
mp_raise_TypeError(NULL);
diff --git a/py/runtime.c b/py/runtime.c
index 3434d9cc4..99f7f6109 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -277,7 +277,7 @@ mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) {
case MP_UNARY_OP_HASH:
return arg;
case MP_UNARY_OP_POSITIVE:
- case MP_UNARY_OP_INT:
+ case MP_UNARY_OP_INT_MAYBE:
return arg;
case MP_UNARY_OP_NEGATIVE:
// check for overflow
@@ -324,32 +324,23 @@ mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) {
// if arg==mp_const_none.
return mp_const_true;
}
- #if MICROPY_PY_BUILTINS_FLOAT
- if (op == MP_UNARY_OP_FLOAT_MAYBE
+ if (op == MP_UNARY_OP_INT_MAYBE
+ #if MICROPY_PY_BUILTINS_FLOAT
+ || op == MP_UNARY_OP_FLOAT_MAYBE
#if MICROPY_PY_BUILTINS_COMPLEX
|| op == MP_UNARY_OP_COMPLEX_MAYBE
#endif
+ #endif
) {
+ // These operators may return MP_OBJ_NULL if they are not supported by the type.
return MP_OBJ_NULL;
}
- #endif
- // With MP_UNARY_OP_INT, mp_unary_op() becomes a fallback for mp_obj_get_int().
- // In this case provide a more focused error message to not confuse, e.g. chr(1.0)
#if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
- if (op == MP_UNARY_OP_INT) {
- mp_raise_TypeError(MP_ERROR_TEXT("can't convert to int"));
- } else {
- mp_raise_TypeError(MP_ERROR_TEXT("unsupported type for operator"));
- }
+ mp_raise_TypeError(MP_ERROR_TEXT("unsupported type for operator"));
#else
- if (op == MP_UNARY_OP_INT) {
- mp_raise_msg_varg(&mp_type_TypeError,
- MP_ERROR_TEXT("can't convert %s to int"), mp_obj_get_type_str(arg));
- } else {
- mp_raise_msg_varg(&mp_type_TypeError,
- MP_ERROR_TEXT("unsupported type for %q: '%s'"),
- mp_unary_op_method_name[op], mp_obj_get_type_str(arg));
- }
+ mp_raise_msg_varg(&mp_type_TypeError,
+ MP_ERROR_TEXT("unsupported type for %q: '%s'"),
+ mp_unary_op_method_name[op], mp_obj_get_type_str(arg));
#endif
}
}
@@ -1700,6 +1691,16 @@ NORETURN void mp_raise_StopIteration(mp_obj_t arg) {
}
}
+NORETURN void mp_raise_TypeError_int_conversion(mp_const_obj_t arg) {
+ #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
+ (void)arg;
+ mp_raise_TypeError(MP_ERROR_TEXT("can't convert to int"));
+ #else
+ mp_raise_msg_varg(&mp_type_TypeError,
+ MP_ERROR_TEXT("can't convert %s to int"), mp_obj_get_type_str(arg));
+ #endif
+}
+
NORETURN void mp_raise_OSError(int errno_) {
mp_raise_type_arg(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno_));
}
diff --git a/py/runtime.h b/py/runtime.h
index d57c25c92..9b99e594b 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -198,6 +198,7 @@ NORETURN void mp_raise_NotImplementedError(mp_rom_error_text_t msg);
NORETURN void mp_raise_type_arg(const mp_obj_type_t *exc_type, mp_obj_t arg);
NORETURN void mp_raise_StopIteration(mp_obj_t arg);
+NORETURN void mp_raise_TypeError_int_conversion(mp_const_obj_t arg);
NORETURN void mp_raise_OSError(int errno_);
NORETURN void mp_raise_OSError_with_filename(int errno_, const char *filename);
NORETURN void mp_raise_recursion_depth(void);
diff --git a/py/runtime0.h b/py/runtime0.h
index c82a4717f..6ef2d727c 100644
--- a/py/runtime0.h
+++ b/py/runtime0.h
@@ -75,7 +75,7 @@ typedef enum {
MP_UNARY_OP_LEN, // __len__
MP_UNARY_OP_HASH, // __hash__; must return a small int
MP_UNARY_OP_ABS, // __abs__
- MP_UNARY_OP_INT, // __int__
+ MP_UNARY_OP_INT_MAYBE, // __int__; must return MP_OBJ_NULL, or an object satisfying mp_obj_is_int()
MP_UNARY_OP_FLOAT_MAYBE, // __float__
MP_UNARY_OP_COMPLEX_MAYBE, // __complex__
MP_UNARY_OP_SIZEOF, // for sys.getsizeof()