py/runtime: Implement dispatch for "reverse op" special methods.
If, for class X, X.__add__(Y) doesn't exist (or returns NotImplemented), try Y.__radd__(X) instead. This patch could be simpler, but requires undoing operand swap and operation switch to get non-confusing error message in case __radd__ doesn't exist.
This commit is contained in:
parent
de981040b3
commit
eb84a830df
|
@ -35,6 +35,7 @@
|
||||||
#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1)
|
#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1)
|
||||||
#define MICROPY_ENABLE_SCHEDULER (1)
|
#define MICROPY_ENABLE_SCHEDULER (1)
|
||||||
#define MICROPY_PY_DELATTR_SETATTR (1)
|
#define MICROPY_PY_DELATTR_SETATTR (1)
|
||||||
|
#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1)
|
||||||
#define MICROPY_PY_BUILTINS_HELP (1)
|
#define MICROPY_PY_BUILTINS_HELP (1)
|
||||||
#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
|
#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
|
||||||
#define MICROPY_PY_SYS_GETSIZEOF (1)
|
#define MICROPY_PY_SYS_GETSIZEOF (1)
|
||||||
|
|
|
@ -759,11 +759,19 @@ typedef double mp_float_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Whether to support complete set of special methods
|
// Whether to support complete set of special methods
|
||||||
// for user classes, otherwise only the most used
|
// for user classes, or only the most used ones. "Reverse"
|
||||||
|
// methods are controlled by MICROPY_PY_REVERSE_SPECIAL_METHODS
|
||||||
|
// below.
|
||||||
#ifndef MICROPY_PY_ALL_SPECIAL_METHODS
|
#ifndef MICROPY_PY_ALL_SPECIAL_METHODS
|
||||||
#define MICROPY_PY_ALL_SPECIAL_METHODS (0)
|
#define MICROPY_PY_ALL_SPECIAL_METHODS (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Whether to support reverse arithmetic operarions methods
|
||||||
|
// (__radd__, etc.)
|
||||||
|
#ifndef MICROPY_PY_REVERSE_SPECIAL_METHODS
|
||||||
|
#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
// Whether to support compile function
|
// Whether to support compile function
|
||||||
#ifndef MICROPY_PY_BUILTINS_COMPILE
|
#ifndef MICROPY_PY_BUILTINS_COMPILE
|
||||||
#define MICROPY_PY_BUILTINS_COMPILE (0)
|
#define MICROPY_PY_BUILTINS_COMPILE (0)
|
||||||
|
|
|
@ -441,6 +441,13 @@ const qstr mp_binary_op_method_name[] = {
|
||||||
MP_BINARY_OP_INPLACE_TRUE_DIVIDE,
|
MP_BINARY_OP_INPLACE_TRUE_DIVIDE,
|
||||||
MP_BINARY_OP_INPLACE_MODULO,
|
MP_BINARY_OP_INPLACE_MODULO,
|
||||||
MP_BINARY_OP_INPLACE_POWER,*/
|
MP_BINARY_OP_INPLACE_POWER,*/
|
||||||
|
|
||||||
|
#if MICROPY_PY_REVERSE_SPECIAL_METHODS
|
||||||
|
[MP_BINARY_OP_REVERSE_ADD] = MP_QSTR___radd__,
|
||||||
|
[MP_BINARY_OP_REVERSE_SUBTRACT] = MP_QSTR___rsub__,
|
||||||
|
[MP_BINARY_OP_REVERSE_MULTIPLY] = MP_QSTR___rmul__,
|
||||||
|
#endif
|
||||||
|
|
||||||
[MP_BINARY_OP_LESS] = MP_QSTR___lt__,
|
[MP_BINARY_OP_LESS] = MP_QSTR___lt__,
|
||||||
[MP_BINARY_OP_MORE] = MP_QSTR___gt__,
|
[MP_BINARY_OP_MORE] = MP_QSTR___gt__,
|
||||||
[MP_BINARY_OP_EQUAL] = MP_QSTR___eq__,
|
[MP_BINARY_OP_EQUAL] = MP_QSTR___eq__,
|
||||||
|
|
15
py/runtime.c
15
py/runtime.c
|
@ -555,7 +555,20 @@ generic_binary_op:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO implement dispatch for reverse binary ops
|
#if MICROPY_PY_REVERSE_SPECIAL_METHODS
|
||||||
|
if (op >= MP_BINARY_OP_OR && op <= MP_BINARY_OP_REVERSE_POWER) {
|
||||||
|
mp_obj_t t = rhs;
|
||||||
|
rhs = lhs;
|
||||||
|
lhs = t;
|
||||||
|
if (op <= MP_BINARY_OP_POWER) {
|
||||||
|
op += MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR;
|
||||||
|
goto generic_binary_op;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert __rop__ back to __op__ for error message
|
||||||
|
op -= MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
unsupported_op:
|
unsupported_op:
|
||||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||||
|
|
|
@ -101,6 +101,23 @@ typedef enum {
|
||||||
// Operations below this line don't appear in bytecode, they
|
// Operations below this line don't appear in bytecode, they
|
||||||
// just identify special methods.
|
// just identify special methods.
|
||||||
|
|
||||||
|
// MP_BINARY_OP_REVERSE_* must follow immediately after MP_BINARY_OP_*
|
||||||
|
#if MICROPY_PY_REVERSE_SPECIAL_METHODS
|
||||||
|
MP_BINARY_OP_REVERSE_OR,
|
||||||
|
MP_BINARY_OP_REVERSE_XOR,
|
||||||
|
MP_BINARY_OP_REVERSE_AND,
|
||||||
|
MP_BINARY_OP_REVERSE_LSHIFT,
|
||||||
|
MP_BINARY_OP_REVERSE_RSHIFT,
|
||||||
|
MP_BINARY_OP_REVERSE_ADD,
|
||||||
|
|
||||||
|
MP_BINARY_OP_REVERSE_SUBTRACT,
|
||||||
|
MP_BINARY_OP_REVERSE_MULTIPLY,
|
||||||
|
MP_BINARY_OP_REVERSE_FLOOR_DIVIDE,
|
||||||
|
MP_BINARY_OP_REVERSE_TRUE_DIVIDE,
|
||||||
|
MP_BINARY_OP_REVERSE_MODULO,
|
||||||
|
MP_BINARY_OP_REVERSE_POWER,
|
||||||
|
#endif
|
||||||
|
|
||||||
MP_BINARY_OP_DIVMOD, // not emitted by the compiler but supported by the runtime
|
MP_BINARY_OP_DIVMOD, // not emitted by the compiler but supported by the runtime
|
||||||
|
|
||||||
MP_BINARY_OP_LAST,
|
MP_BINARY_OP_LAST,
|
||||||
|
|
Loading…
Reference in New Issue