summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2023-05-12 23:16:37 +1000
committerDamien George <damien@micropython.org>2023-05-19 13:44:00 +1000
commitea7031faff9efe6803d8a8f67ad2e3b4a6d390e3 (patch)
tree71faadf644033b57a5e1339102148719ae20a155 /py
parent4b57330465b98df30ef8a10e19a0e197b5797550 (diff)
py/runtime: If inplace binop fails then try corresponding normal binop.
The code that handles inplace-operator to normal-binary-operator fallback is moved in this commit from py/objtype.c to py/runtime.c, making it apply to all types, not just user classes. Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'py')
-rw-r--r--py/objtype.c13
-rw-r--r--py/runtime.c9
2 files changed, 10 insertions, 12 deletions
diff --git a/py/objtype.c b/py/objtype.c
index 88d1c8ebe..04bdf5acd 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -534,7 +534,6 @@ STATIC mp_obj_t instance_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t
// Note: For ducktyping, CPython does not look in the instance members or use
// __getattr__ or __getattribute__. It only looks in the class dictionary.
mp_obj_instance_t *lhs = MP_OBJ_TO_PTR(lhs_in);
-retry:;
qstr op_name = mp_binary_op_method_name[op];
/* Still try to lookup native slot
if (op_name == 0) {
@@ -559,22 +558,12 @@ retry:;
res = mp_call_method_n_kw(1, 0, dest);
res = op == MP_BINARY_OP_CONTAINS ? mp_obj_new_bool(mp_obj_is_true(res)) : res;
} else {
- // If this was an inplace method, fallback to normal method
- // https://docs.python.org/3/reference/datamodel.html#object.__iadd__ :
- // "If a specific method is not defined, the augmented assignment
- // falls back to the normal methods."
- if (op >= MP_BINARY_OP_INPLACE_OR && op <= MP_BINARY_OP_INPLACE_POWER) {
- op -= MP_BINARY_OP_INPLACE_OR - MP_BINARY_OP_OR;
- goto retry;
- }
return MP_OBJ_NULL; // op not supported
}
#if MICROPY_PY_BUILTINS_NOTIMPLEMENTED
// NotImplemented means "try other fallbacks (like calling __rop__
- // instead of __op__) and if nothing works, raise TypeError". As
- // MicroPython doesn't implement any fallbacks, signal to raise
- // TypeError right away.
+ // instead of __op__) and if nothing works, raise TypeError".
if (res == mp_const_notimplemented) {
return MP_OBJ_NULL; // op not supported
}
diff --git a/py/runtime.c b/py/runtime.c
index 47e094763..3434d9cc4 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -625,6 +625,15 @@ generic_binary_op:
}
}
+ // If this was an inplace method, fallback to the corresponding normal method.
+ // https://docs.python.org/3/reference/datamodel.html#object.__iadd__ :
+ // "If a specific method is not defined, the augmented assignment falls back
+ // to the normal methods."
+ if (op >= MP_BINARY_OP_INPLACE_OR && op <= MP_BINARY_OP_INPLACE_POWER) {
+ op += MP_BINARY_OP_OR - MP_BINARY_OP_INPLACE_OR;
+ goto generic_binary_op;
+ }
+
#if MICROPY_PY_REVERSE_SPECIAL_METHODS
if (op >= MP_BINARY_OP_OR && op <= MP_BINARY_OP_POWER) {
mp_obj_t t = rhs;