py: Make UNARY_OP_NOT a first-class op, to agree with Py not semantics.

Fixes #1684 and makes "not" match Python semantics.  The code is also
simplified (the separate MP_BC_NOT opcode is removed) and the patch saves
68 bytes for bare-arm/ and 52 bytes for minimal/.

Previously "not x" was implemented as !mp_unary_op(x, MP_UNARY_OP_BOOL),
so any given object only needs to implement MP_UNARY_OP_BOOL (and the VM
had a special opcode to do the ! bit).

With this patch "not x" is implemented as mp_unary_op(x, MP_UNARY_OP_NOT),
but this operation is caught at the start of mp_unary_op and dispatched as
!mp_obj_is_true(x).  mp_obj_is_true has special logic to test for
truthness, and is the correct way to handle the not operation.
This commit is contained in:
Damien George
2015-12-08 12:28:11 +00:00
parent e242b1785f
commit bdbe8c9ae2
9 changed files with 12 additions and 47 deletions

View File

@@ -184,7 +184,10 @@ void mp_delete_global(qstr qst) {
mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) {
DEBUG_OP_printf("unary " UINT_FMT " %p\n", op, arg);
if (MP_OBJ_IS_SMALL_INT(arg)) {
if (op == MP_UNARY_OP_NOT) {
// "not x" is the negative of whether "x" is true per Python semantics
return mp_obj_new_bool(mp_obj_is_true(arg) == 0);
} else if (MP_OBJ_IS_SMALL_INT(arg)) {
mp_int_t val = MP_OBJ_SMALL_INT_VALUE(arg);
switch (op) {
case MP_UNARY_OP_BOOL: