py: Tidy up BINARY_OPs; negation done by special NOT bytecode.

IS_NOT and NOT_IN are now compiled to IS + NOT and IN + NOT, with a new
special NOT bytecode.
This commit is contained in:
Damien George 2014-02-01 23:04:09 +00:00
parent 7e5fb24e3b
commit 9aa2a527b5
17 changed files with 144 additions and 135 deletions

View File

@ -63,8 +63,9 @@
#define MP_BC_POP_EXCEPT (0x55) #define MP_BC_POP_EXCEPT (0x55)
#define MP_BC_UNWIND_JUMP (0x56) // rel byte code offset, 16-bit signed, in excess; then a byte #define MP_BC_UNWIND_JUMP (0x56) // rel byte code offset, 16-bit signed, in excess; then a byte
#define MP_BC_UNARY_OP (0x60) // byte #define MP_BC_NOT (0x60)
#define MP_BC_BINARY_OP (0x61) // byte #define MP_BC_UNARY_OP (0x61) // byte
#define MP_BC_BINARY_OP (0x62) // byte
#define MP_BC_BUILD_TUPLE (0x70) // uint #define MP_BC_BUILD_TUPLE (0x70) // uint
#define MP_BC_BUILD_LIST (0x71) // uint #define MP_BC_BUILD_LIST (0x71) // uint

View File

@ -1466,9 +1466,9 @@ void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var,
compile_node(comp, pn_var); compile_node(comp, pn_var);
compile_node(comp, pn_end); compile_node(comp, pn_end);
if (MP_PARSE_NODE_LEAF_ARG(pn_step) >= 0) { if (MP_PARSE_NODE_LEAF_ARG(pn_step) >= 0) {
EMIT_ARG(binary_op, RT_COMPARE_OP_LESS); EMIT_ARG(binary_op, RT_BINARY_OP_LESS);
} else { } else {
EMIT_ARG(binary_op, RT_COMPARE_OP_MORE); EMIT_ARG(binary_op, RT_BINARY_OP_MORE);
} }
EMIT_ARG(pop_jump_if_true, top_label); EMIT_ARG(pop_jump_if_true, top_label);
@ -1605,7 +1605,7 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except,
} }
EMIT(dup_top); EMIT(dup_top);
compile_node(comp, pns_exception_expr); compile_node(comp, pns_exception_expr);
EMIT_ARG(binary_op, RT_COMPARE_OP_EXCEPTION_MATCH); EMIT_ARG(binary_op, RT_BINARY_OP_EXCEPTION_MATCH);
EMIT_ARG(pop_jump_if_false, end_finally_label); EMIT_ARG(pop_jump_if_false, end_finally_label);
} }
@ -1912,21 +1912,7 @@ void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) { void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
compile_node(comp, pns->nodes[0]); compile_node(comp, pns->nodes[0]);
#if MICROPY_EMIT_CPYTHON
EMIT_ARG(unary_op, RT_UNARY_OP_NOT); EMIT_ARG(unary_op, RT_UNARY_OP_NOT);
#else
// eliminate use of NOT byte code
int l_load_false = comp_next_label(comp);
int l_done = comp_next_label(comp);
int stack_size = EMIT(get_stack_size);
EMIT_ARG(pop_jump_if_true, l_load_false);
EMIT_ARG(load_const_tok, MP_TOKEN_KW_TRUE);
EMIT_ARG(jump, l_done);
EMIT_ARG(label_assign, l_load_false);
EMIT_ARG(load_const_tok, MP_TOKEN_KW_FALSE);
EMIT_ARG(label_assign, l_done);
EMIT_ARG(set_stack_size, stack_size); // force stack size since it counts 1 pop and 2 pushes statically, but really it's 1 pop and 1 push dynamically
#endif
} }
void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) { void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
@ -1947,26 +1933,26 @@ void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) { if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) {
rt_binary_op_t op; rt_binary_op_t op;
switch (MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])) { switch (MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])) {
case MP_TOKEN_OP_LESS: op = RT_COMPARE_OP_LESS; break; case MP_TOKEN_OP_LESS: op = RT_BINARY_OP_LESS; break;
case MP_TOKEN_OP_MORE: op = RT_COMPARE_OP_MORE; break; case MP_TOKEN_OP_MORE: op = RT_BINARY_OP_MORE; break;
case MP_TOKEN_OP_DBL_EQUAL: op = RT_COMPARE_OP_EQUAL; break; case MP_TOKEN_OP_DBL_EQUAL: op = RT_BINARY_OP_EQUAL; break;
case MP_TOKEN_OP_LESS_EQUAL: op = RT_COMPARE_OP_LESS_EQUAL; break; case MP_TOKEN_OP_LESS_EQUAL: op = RT_BINARY_OP_LESS_EQUAL; break;
case MP_TOKEN_OP_MORE_EQUAL: op = RT_COMPARE_OP_MORE_EQUAL; break; case MP_TOKEN_OP_MORE_EQUAL: op = RT_BINARY_OP_MORE_EQUAL; break;
case MP_TOKEN_OP_NOT_EQUAL: op = RT_COMPARE_OP_NOT_EQUAL; break; case MP_TOKEN_OP_NOT_EQUAL: op = RT_BINARY_OP_NOT_EQUAL; break;
case MP_TOKEN_KW_IN: op = RT_COMPARE_OP_IN; break; case MP_TOKEN_KW_IN: op = RT_BINARY_OP_IN; break;
default: assert(0); op = RT_COMPARE_OP_LESS; // shouldn't happen default: assert(0); op = RT_BINARY_OP_LESS; // shouldn't happen
} }
EMIT_ARG(binary_op, op); EMIT_ARG(binary_op, op);
} else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])) { } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])) {
mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i]; mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];
int kind = MP_PARSE_NODE_STRUCT_KIND(pns2); int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
if (kind == PN_comp_op_not_in) { if (kind == PN_comp_op_not_in) {
EMIT_ARG(binary_op, RT_COMPARE_OP_NOT_IN); EMIT_ARG(binary_op, RT_BINARY_OP_NOT_IN);
} else if (kind == PN_comp_op_is) { } else if (kind == PN_comp_op_is) {
if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) { if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
EMIT_ARG(binary_op, RT_COMPARE_OP_IS); EMIT_ARG(binary_op, RT_BINARY_OP_IS);
} else { } else {
EMIT_ARG(binary_op, RT_COMPARE_OP_IS_NOT); EMIT_ARG(binary_op, RT_BINARY_OP_IS_NOT);
} }
} else { } else {
// shouldn't happen // shouldn't happen

View File

@ -600,13 +600,32 @@ static void emit_bc_pop_except(emit_t *emit) {
} }
static void emit_bc_unary_op(emit_t *emit, rt_unary_op_t op) { static void emit_bc_unary_op(emit_t *emit, rt_unary_op_t op) {
emit_pre(emit, 0); if (op == RT_UNARY_OP_NOT) {
emit_write_byte_code_byte_byte(emit, MP_BC_UNARY_OP, op); emit_pre(emit, 0);
emit_write_byte_code_byte_byte(emit, MP_BC_UNARY_OP, RT_UNARY_OP_BOOL);
emit_pre(emit, 0);
emit_write_byte_code_byte(emit, MP_BC_NOT);
} else {
emit_pre(emit, 0);
emit_write_byte_code_byte_byte(emit, MP_BC_UNARY_OP, op);
}
} }
static void emit_bc_binary_op(emit_t *emit, rt_binary_op_t op) { static void emit_bc_binary_op(emit_t *emit, rt_binary_op_t op) {
bool invert = false;
if (op == RT_BINARY_OP_NOT_IN) {
invert = true;
op = RT_BINARY_OP_IN;
} else if (op == RT_BINARY_OP_IS_NOT) {
invert = true;
op = RT_BINARY_OP_IS;
}
emit_pre(emit, -1); emit_pre(emit, -1);
emit_write_byte_code_byte_byte(emit, MP_BC_BINARY_OP, op); emit_write_byte_code_byte_byte(emit, MP_BC_BINARY_OP, op);
if (invert) {
emit_pre(emit, 0);
emit_write_byte_code_byte(emit, MP_BC_NOT);
}
} }
static void emit_bc_build_tuple(emit_t *emit, int n_args) { static void emit_bc_build_tuple(emit_t *emit, int n_args) {

View File

@ -545,10 +545,10 @@ static void emit_cpy_unary_op(emit_t *emit, rt_unary_op_t op) {
emit_pre(emit, 0, 1); emit_pre(emit, 0, 1);
if (emit->pass == PASS_3) { if (emit->pass == PASS_3) {
switch (op) { switch (op) {
case RT_UNARY_OP_NOT: printf("UNARY_NOT\n"); break;
case RT_UNARY_OP_POSITIVE: printf("UNARY_POSITIVE\n"); break; case RT_UNARY_OP_POSITIVE: printf("UNARY_POSITIVE\n"); break;
case RT_UNARY_OP_NEGATIVE: printf("UNARY_NEGATIVE\n"); break; case RT_UNARY_OP_NEGATIVE: printf("UNARY_NEGATIVE\n"); break;
case RT_UNARY_OP_INVERT: printf("UNARY_INVERT\n"); break; case RT_UNARY_OP_INVERT: printf("UNARY_INVERT\n"); break;
case RT_UNARY_OP_NOT: printf("UNARY_NOT\n"); break;
default: assert(0); default: assert(0);
} }
} }
@ -589,17 +589,17 @@ static void emit_cpy_binary_op(emit_t *emit, rt_binary_op_t op) {
case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: printf("INPLACE_TRUE_DIVIDE\n"); break; case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: printf("INPLACE_TRUE_DIVIDE\n"); break;
case RT_BINARY_OP_INPLACE_MODULO: printf("INPLACE_MODULO\n"); break; case RT_BINARY_OP_INPLACE_MODULO: printf("INPLACE_MODULO\n"); break;
case RT_BINARY_OP_INPLACE_POWER: printf("INPLACE_POWER\n"); break; case RT_BINARY_OP_INPLACE_POWER: printf("INPLACE_POWER\n"); break;
case RT_COMPARE_OP_LESS: printf("COMPARE_OP <\n"); break; case RT_BINARY_OP_LESS: printf("COMPARE_OP <\n"); break;
case RT_COMPARE_OP_MORE: printf("COMPARE_OP >\n"); break; case RT_BINARY_OP_MORE: printf("COMPARE_OP >\n"); break;
case RT_COMPARE_OP_EQUAL: printf("COMPARE_OP ==\n"); break; case RT_BINARY_OP_EQUAL: printf("COMPARE_OP ==\n"); break;
case RT_COMPARE_OP_LESS_EQUAL: printf("COMPARE_OP <=\n"); break; case RT_BINARY_OP_LESS_EQUAL: printf("COMPARE_OP <=\n"); break;
case RT_COMPARE_OP_MORE_EQUAL: printf("COMPARE_OP >=\n"); break; case RT_BINARY_OP_MORE_EQUAL: printf("COMPARE_OP >=\n"); break;
case RT_COMPARE_OP_NOT_EQUAL: printf("COMPARE_OP !=\n"); break; case RT_BINARY_OP_NOT_EQUAL: printf("COMPARE_OP !=\n"); break;
case RT_COMPARE_OP_IN: printf("COMPARE_OP in\n"); break; case RT_BINARY_OP_IN: printf("COMPARE_OP in\n"); break;
case RT_COMPARE_OP_NOT_IN: printf("COMPARE_OP not in\n"); break; case RT_BINARY_OP_IS: printf("COMPARE_OP is\n"); break;
case RT_COMPARE_OP_IS: printf("COMPARE_OP is\n"); break; case RT_BINARY_OP_EXCEPTION_MATCH: printf("COMPARE_OP exception match\n"); break;
case RT_COMPARE_OP_IS_NOT: printf("COMPARE_OP is not\n"); break; case RT_BINARY_OP_NOT_IN: printf("COMPARE_OP not in\n"); break;
case RT_COMPARE_OP_EXCEPTION_MATCH: printf("COMPARE_OP exception match\n"); break; case RT_BINARY_OP_IS_NOT: printf("COMPARE_OP is not\n"); break;
default: assert(0); default: assert(0);
} }
} }

View File

@ -1017,7 +1017,7 @@ static void emit_native_binary_op(emit_t *emit, rt_binary_op_t op) {
asm_thumb_add_reg_reg_reg(emit->as, REG_ARG_2, REG_ARG_2, REG_ARG_3); asm_thumb_add_reg_reg_reg(emit->as, REG_ARG_2, REG_ARG_2, REG_ARG_3);
#endif #endif
emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2); emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
} else if (op == RT_COMPARE_OP_LESS) { } else if (op == RT_BINARY_OP_LESS) {
#if N_X64 #if N_X64
asm_x64_xor_r64_to_r64(emit->as, REG_RET, REG_RET); asm_x64_xor_r64_to_r64(emit->as, REG_RET, REG_RET);
asm_x64_cmp_r64_with_r64(emit->as, REG_ARG_3, REG_ARG_2); asm_x64_cmp_r64_with_r64(emit->as, REG_ARG_3, REG_ARG_2);

View File

@ -116,7 +116,7 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
// If o2 is long int, dispatch to its virtual methods // If o2 is long int, dispatch to its virtual methods
mp_obj_base_t *o = o2; mp_obj_base_t *o = o2;
if (o->type->binary_op != NULL) { if (o->type->binary_op != NULL) {
mp_obj_t r = o->type->binary_op(RT_COMPARE_OP_EQUAL, o2, o1); mp_obj_t r = o->type->binary_op(RT_BINARY_OP_EQUAL, o2, o1);
return r == mp_const_true ? true : false; return r == mp_const_true ? true : false;
} }
} }
@ -127,7 +127,7 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
} else { } else {
mp_obj_base_t *o = o1; mp_obj_base_t *o = o1;
if (o->type->binary_op != NULL) { if (o->type->binary_op != NULL) {
mp_obj_t r = o->type->binary_op(RT_COMPARE_OP_EQUAL, o1, o2); mp_obj_t r = o->type->binary_op(RT_BINARY_OP_EQUAL, o1, o2);
if (r != MP_OBJ_NULL) { if (r != MP_OBJ_NULL) {
return r == mp_const_true ? true : false; return r == mp_const_true ? true : false;
} }

View File

@ -65,11 +65,10 @@ static mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
return elem->value; return elem->value;
} }
} }
case RT_COMPARE_OP_IN: case RT_BINARY_OP_IN:
case RT_COMPARE_OP_NOT_IN:
{ {
mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP); mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (elem == NULL)); return MP_BOOL(elem != NULL);
} }
default: default:
// op not supported // op not supported
@ -380,7 +379,7 @@ static mp_obj_t dict_view_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
/* only supported for the 'keys' kind until sets and dicts are refactored */ /* only supported for the 'keys' kind until sets and dicts are refactored */
mp_obj_dict_view_t *o = lhs_in; mp_obj_dict_view_t *o = lhs_in;
if (o->kind != MP_DICT_VIEW_KEYS) return NULL; if (o->kind != MP_DICT_VIEW_KEYS) return NULL;
if (op != RT_COMPARE_OP_IN && op != RT_COMPARE_OP_NOT_IN) return NULL; if (op != RT_BINARY_OP_IN) return NULL;
return dict_binary_op(op, o->dict, rhs_in); return dict_binary_op(op, o->dict, rhs_in);
} }

View File

@ -101,10 +101,10 @@ mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs_in) {
case RT_BINARY_OP_TRUE_DIVIDE: case RT_BINARY_OP_TRUE_DIVIDE:
case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: lhs_val /= rhs_val; break; case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: lhs_val /= rhs_val; break;
case RT_COMPARE_OP_LESS: return MP_BOOL(lhs_val < rhs_val); case RT_BINARY_OP_LESS: return MP_BOOL(lhs_val < rhs_val);
case RT_COMPARE_OP_MORE: return MP_BOOL(lhs_val > rhs_val); case RT_BINARY_OP_MORE: return MP_BOOL(lhs_val > rhs_val);
case RT_COMPARE_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val); case RT_BINARY_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val);
case RT_COMPARE_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val); case RT_BINARY_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val);
return NULL; // op not supported return NULL; // op not supported
} }

View File

@ -103,17 +103,17 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
case RT_BINARY_OP_INPLACE_RSHIFT: case RT_BINARY_OP_INPLACE_RSHIFT:
lhs->val >>= (int)rhs_val; return lhs; lhs->val >>= (int)rhs_val; return lhs;
case RT_COMPARE_OP_LESS: case RT_BINARY_OP_LESS:
return MP_BOOL(lhs->val < rhs_val); return MP_BOOL(lhs->val < rhs_val);
case RT_COMPARE_OP_MORE: case RT_BINARY_OP_MORE:
return MP_BOOL(lhs->val > rhs_val); return MP_BOOL(lhs->val > rhs_val);
case RT_COMPARE_OP_LESS_EQUAL: case RT_BINARY_OP_LESS_EQUAL:
return MP_BOOL(lhs->val <= rhs_val); return MP_BOOL(lhs->val <= rhs_val);
case RT_COMPARE_OP_MORE_EQUAL: case RT_BINARY_OP_MORE_EQUAL:
return MP_BOOL(lhs->val >= rhs_val); return MP_BOOL(lhs->val >= rhs_val);
case RT_COMPARE_OP_EQUAL: case RT_BINARY_OP_EQUAL:
return MP_BOOL(lhs->val == rhs_val); return MP_BOOL(lhs->val == rhs_val);
case RT_COMPARE_OP_NOT_EQUAL: case RT_BINARY_OP_NOT_EQUAL:
return MP_BOOL(lhs->val != rhs_val); return MP_BOOL(lhs->val != rhs_val);
default: default:

View File

@ -67,7 +67,7 @@ static mp_obj_t list_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp
return NULL; return NULL;
} }
// Don't pass RT_COMPARE_OP_NOT_EQUAL here // Don't pass RT_BINARY_OP_NOT_EQUAL here
static bool list_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) { static bool list_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) {
assert(MP_OBJ_IS_TYPE(self_in, &list_type)); assert(MP_OBJ_IS_TYPE(self_in, &list_type));
if (!MP_OBJ_IS_TYPE(another_in, &list_type)) { if (!MP_OBJ_IS_TYPE(another_in, &list_type)) {
@ -75,19 +75,19 @@ static bool list_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) {
} }
mp_obj_list_t *self = self_in; mp_obj_list_t *self = self_in;
mp_obj_list_t *another = another_in; mp_obj_list_t *another = another_in;
if (op == RT_COMPARE_OP_EQUAL && self->len != another->len) { if (op == RT_BINARY_OP_EQUAL && self->len != another->len) {
return false; return false;
} }
// Let's deal only with > & >= // Let's deal only with > & >=
if (op == RT_COMPARE_OP_LESS || op == RT_COMPARE_OP_LESS_EQUAL) { if (op == RT_BINARY_OP_LESS || op == RT_BINARY_OP_LESS_EQUAL) {
mp_obj_t t = self; mp_obj_t t = self;
self = another; self = another;
another = t; another = t;
if (op == RT_COMPARE_OP_LESS) { if (op == RT_BINARY_OP_LESS) {
op = RT_COMPARE_OP_MORE; op = RT_BINARY_OP_MORE;
} else { } else {
op = RT_COMPARE_OP_MORE_EQUAL; op = RT_BINARY_OP_MORE_EQUAL;
} }
} }
@ -96,7 +96,7 @@ static bool list_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) {
bool rel_status; bool rel_status;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
eq_status = mp_obj_equal(self->items[i], another->items[i]); eq_status = mp_obj_equal(self->items[i], another->items[i]);
if (op == RT_COMPARE_OP_EQUAL && !eq_status) { if (op == RT_BINARY_OP_EQUAL && !eq_status) {
return false; return false;
} }
rel_status = (rt_binary_op(op, self->items[i], another->items[i]) == mp_const_true); rel_status = (rt_binary_op(op, self->items[i], another->items[i]) == mp_const_true);
@ -113,7 +113,7 @@ static bool list_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) {
// ... then longer list length wins (we deal only with >) // ... then longer list length wins (we deal only with >)
return false; return false;
} }
} else if (op == RT_COMPARE_OP_MORE) { } else if (op == RT_BINARY_OP_MORE) {
// Otherwise, if we have strict relation, equality means failure // Otherwise, if we have strict relation, equality means failure
return false; return false;
} }
@ -169,14 +169,14 @@ static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items); mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items);
return s; return s;
} }
case RT_COMPARE_OP_EQUAL: case RT_BINARY_OP_EQUAL:
case RT_COMPARE_OP_LESS: case RT_BINARY_OP_LESS:
case RT_COMPARE_OP_LESS_EQUAL: case RT_BINARY_OP_LESS_EQUAL:
case RT_COMPARE_OP_MORE: case RT_BINARY_OP_MORE:
case RT_COMPARE_OP_MORE_EQUAL: case RT_BINARY_OP_MORE_EQUAL:
return MP_BOOL(list_cmp_helper(op, lhs, rhs)); return MP_BOOL(list_cmp_helper(op, lhs, rhs));
case RT_COMPARE_OP_NOT_EQUAL: case RT_BINARY_OP_NOT_EQUAL:
return MP_BOOL(!list_cmp_helper(RT_COMPARE_OP_EQUAL, lhs, rhs)); return MP_BOOL(!list_cmp_helper(RT_BINARY_OP_EQUAL, lhs, rhs));
default: default:
// op not supported // op not supported
@ -237,7 +237,7 @@ static mp_obj_t list_pop(uint n_args, const mp_obj_t *args) {
// TODO make this conform to CPython's definition of sort // TODO make this conform to CPython's definition of sort
static void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, bool reversed) { static void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, bool reversed) {
int op = reversed ? RT_COMPARE_OP_MORE : RT_COMPARE_OP_LESS; int op = reversed ? RT_BINARY_OP_MORE : RT_BINARY_OP_LESS;
while (head < tail) { while (head < tail) {
mp_obj_t *h = head - 1; mp_obj_t *h = head - 1;
mp_obj_t *t = tail; mp_obj_t *t = tail;

View File

@ -396,24 +396,23 @@ static mp_obj_t set_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
return set_intersect(lhs, rhs); return set_intersect(lhs, rhs);
case RT_BINARY_OP_INPLACE_SUBTRACT: case RT_BINARY_OP_INPLACE_SUBTRACT:
return set_diff(2, args); return set_diff(2, args);
case RT_COMPARE_OP_LESS: case RT_BINARY_OP_LESS:
return set_issubset_proper(lhs, rhs); return set_issubset_proper(lhs, rhs);
case RT_COMPARE_OP_MORE: case RT_BINARY_OP_MORE:
return set_issuperset_proper(lhs, rhs); return set_issuperset_proper(lhs, rhs);
case RT_COMPARE_OP_EQUAL: case RT_BINARY_OP_EQUAL:
return set_equal(lhs, rhs); return set_equal(lhs, rhs);
case RT_COMPARE_OP_LESS_EQUAL: case RT_BINARY_OP_LESS_EQUAL:
return set_issubset(lhs, rhs); return set_issubset(lhs, rhs);
case RT_COMPARE_OP_MORE_EQUAL: case RT_BINARY_OP_MORE_EQUAL:
return set_issuperset(lhs, rhs); return set_issuperset(lhs, rhs);
case RT_COMPARE_OP_NOT_EQUAL: case RT_BINARY_OP_NOT_EQUAL:
return MP_BOOL(set_equal(lhs, rhs) == mp_const_false); return MP_BOOL(set_equal(lhs, rhs) == mp_const_false);
case RT_COMPARE_OP_IN: case RT_BINARY_OP_IN:
case RT_COMPARE_OP_NOT_IN:
{ {
mp_obj_set_t *o = lhs; mp_obj_set_t *o = lhs;
mp_obj_t elem = mp_set_lookup(&o->set, rhs, MP_MAP_LOOKUP); mp_obj_t elem = mp_set_lookup(&o->set, rhs, MP_MAP_LOOKUP);
return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (elem == NULL)); return MP_BOOL(elem != NULL);
} }
default: default:
// op not supported // op not supported

View File

@ -168,12 +168,11 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
} }
break; break;
case RT_COMPARE_OP_IN: case RT_BINARY_OP_IN:
case RT_COMPARE_OP_NOT_IN:
/* NOTE `a in b` is `b.__contains__(a)` */ /* NOTE `a in b` is `b.__contains__(a)` */
if (MP_OBJ_IS_STR(rhs_in)) { if (MP_OBJ_IS_STR(rhs_in)) {
GET_STR_DATA_LEN(rhs_in, rhs_data, rhs_len); GET_STR_DATA_LEN(rhs_in, rhs_data, rhs_len);
return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (find_subbytes(lhs_data, lhs_len, rhs_data, rhs_len) == NULL)); return MP_BOOL(find_subbytes(lhs_data, lhs_len, rhs_data, rhs_len) != NULL);
} }
break; break;

View File

@ -117,6 +117,7 @@ static mp_obj_t class_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const m
} }
static const qstr unary_op_method_name[] = { static const qstr unary_op_method_name[] = {
[RT_UNARY_OP_NOT] = MP_QSTR_, // don't need to implement this
[RT_UNARY_OP_BOOL] = MP_QSTR___bool__, [RT_UNARY_OP_BOOL] = MP_QSTR___bool__,
[RT_UNARY_OP_LEN] = MP_QSTR___len__, [RT_UNARY_OP_LEN] = MP_QSTR___len__,
//[RT_UNARY_OP_POSITIVE, //[RT_UNARY_OP_POSITIVE,
@ -168,18 +169,16 @@ static const qstr binary_op_method_name[] = {
RT_BINARY_OP_INPLACE_TRUE_DIVIDE, RT_BINARY_OP_INPLACE_TRUE_DIVIDE,
RT_BINARY_OP_INPLACE_MODULO, RT_BINARY_OP_INPLACE_MODULO,
RT_BINARY_OP_INPLACE_POWER, RT_BINARY_OP_INPLACE_POWER,
RT_COMPARE_OP_LESS, RT_BINARY_OP_LESS,
RT_COMPARE_OP_MORE, RT_BINARY_OP_MORE,
RT_COMPARE_OP_EQUAL, RT_BINARY_OP_EQUAL,
RT_COMPARE_OP_LESS_EQUAL, RT_BINARY_OP_LESS_EQUAL,
RT_COMPARE_OP_MORE_EQUAL, RT_BINARY_OP_MORE_EQUAL,
RT_COMPARE_OP_NOT_EQUAL, RT_BINARY_OP_NOT_EQUAL,
RT_COMPARE_OP_IN, RT_BINARY_OP_IN,
RT_COMPARE_OP_NOT_IN, RT_BINARY_OP_IS,
RT_COMPARE_OP_IS,
RT_COMPARE_OP_IS_NOT,
*/ */
[RT_COMPARE_OP_EXCEPTION_MATCH] = MP_QSTR_, // not implemented, used to make sure array has full size [RT_BINARY_OP_EXCEPTION_MATCH] = MP_QSTR_, // not implemented, used to make sure array has full size
}; };
static mp_obj_t class_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { static mp_obj_t class_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {

View File

@ -478,6 +478,7 @@ void rt_store_global(qstr qstr, mp_obj_t obj) {
mp_obj_t rt_unary_op(int op, mp_obj_t arg) { mp_obj_t rt_unary_op(int op, mp_obj_t arg) {
DEBUG_OP_printf("unary %d %p\n", op, arg); DEBUG_OP_printf("unary %d %p\n", op, arg);
if (MP_OBJ_IS_SMALL_INT(arg)) { if (MP_OBJ_IS_SMALL_INT(arg)) {
mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(arg); mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(arg);
switch (op) { switch (op) {
@ -516,28 +517,23 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
// then fail // then fail
// note that list does not implement + or +=, so that inplace_concat is reached first for += // note that list does not implement + or +=, so that inplace_concat is reached first for +=
// deal with is, is not // deal with is
if (op == RT_COMPARE_OP_IS) { if (op == RT_BINARY_OP_IS) {
// TODO: may need to handle strings specially, CPython appears to // TODO: may need to handle strings specially, CPython appears to
// assume all strings are interned (so "is" == "==" for strings) // assume all strings are interned (so "is" == "==" for strings)
return MP_BOOL(lhs == rhs); return MP_BOOL(lhs == rhs);
} }
if (op == RT_COMPARE_OP_IS_NOT) {
// TODO: may need to handle strings specially, CPython appears to
// assume all strings are interned (so "is" == "==" for strings)
return MP_BOOL(lhs != rhs);
}
// deal with == and != for all types // deal with == and != for all types
if (op == RT_COMPARE_OP_EQUAL || op == RT_COMPARE_OP_NOT_EQUAL) { if (op == RT_BINARY_OP_EQUAL || op == RT_BINARY_OP_NOT_EQUAL) {
if (mp_obj_equal(lhs, rhs)) { if (mp_obj_equal(lhs, rhs)) {
if (op == RT_COMPARE_OP_EQUAL) { if (op == RT_BINARY_OP_EQUAL) {
return mp_const_true; return mp_const_true;
} else { } else {
return mp_const_false; return mp_const_false;
} }
} else { } else {
if (op == RT_COMPARE_OP_EQUAL) { if (op == RT_BINARY_OP_EQUAL) {
return mp_const_false; return mp_const_false;
} else { } else {
return mp_const_true; return mp_const_true;
@ -546,7 +542,7 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
} }
// deal with exception_match for all types // deal with exception_match for all types
if (op == RT_COMPARE_OP_EXCEPTION_MATCH) { if (op == RT_BINARY_OP_EXCEPTION_MATCH) {
// TODO properly! at the moment it just compares the exception identifier for equality // TODO properly! at the moment it just compares the exception identifier for equality
if (MP_OBJ_IS_TYPE(lhs, &exception_type) && MP_OBJ_IS_TYPE(rhs, &exception_type)) { if (MP_OBJ_IS_TYPE(lhs, &exception_type) && MP_OBJ_IS_TYPE(rhs, &exception_type)) {
if (mp_obj_exception_get_type(lhs) == mp_obj_exception_get_type(rhs)) { if (mp_obj_exception_get_type(lhs) == mp_obj_exception_get_type(rhs)) {
@ -604,10 +600,10 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
lhs_val = ans; lhs_val = ans;
break; break;
} }
case RT_COMPARE_OP_LESS: return MP_BOOL(lhs_val < rhs_val); break; case RT_BINARY_OP_LESS: return MP_BOOL(lhs_val < rhs_val); break;
case RT_COMPARE_OP_MORE: return MP_BOOL(lhs_val > rhs_val); break; case RT_BINARY_OP_MORE: return MP_BOOL(lhs_val > rhs_val); break;
case RT_COMPARE_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val); break; case RT_BINARY_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val); break;
case RT_COMPARE_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val); break; case RT_BINARY_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val); break;
default: assert(0); default: assert(0);
} }
@ -625,12 +621,12 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
} }
} }
/* deal with `in` and `not in` /* deal with `in`
* *
* NOTE `a in b` is `b.__contains__(a)`, hence why the generic dispatch * NOTE `a in b` is `b.__contains__(a)`, hence why the generic dispatch
* needs to go below * needs to go below
*/ */
if (op == RT_COMPARE_OP_IN || op == RT_COMPARE_OP_NOT_IN) { if (op == RT_BINARY_OP_IN) {
mp_obj_type_t *type = mp_obj_get_type(rhs); mp_obj_type_t *type = mp_obj_get_type(rhs);
if (type->binary_op != NULL) { if (type->binary_op != NULL) {
mp_obj_t res = type->binary_op(op, rhs, lhs); mp_obj_t res = type->binary_op(op, rhs, lhs);
@ -644,10 +640,10 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_t iter = rt_getiter(rhs); mp_obj_t iter = rt_getiter(rhs);
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) { while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
if (mp_obj_equal(next, lhs)) { if (mp_obj_equal(next, lhs)) {
return MP_BOOL(op == RT_COMPARE_OP_IN); return mp_const_true;
} }
} }
return MP_BOOL(op != RT_COMPARE_OP_IN); return mp_const_false;
} }
nlr_jump(mp_obj_new_exception_msg_varg( nlr_jump(mp_obj_new_exception_msg_varg(

View File

@ -4,7 +4,7 @@ typedef enum {
RT_UNARY_OP_POSITIVE, RT_UNARY_OP_POSITIVE,
RT_UNARY_OP_NEGATIVE, RT_UNARY_OP_NEGATIVE,
RT_UNARY_OP_INVERT, RT_UNARY_OP_INVERT,
// Used only for CPython-compatible codegeneration // these are not supported by the runtime and must be synthesised by the emitter
RT_UNARY_OP_NOT, RT_UNARY_OP_NOT,
} rt_unary_op_t; } rt_unary_op_t;
@ -34,18 +34,19 @@ typedef enum {
RT_BINARY_OP_INPLACE_TRUE_DIVIDE, RT_BINARY_OP_INPLACE_TRUE_DIVIDE,
RT_BINARY_OP_INPLACE_MODULO, RT_BINARY_OP_INPLACE_MODULO,
RT_BINARY_OP_INPLACE_POWER, RT_BINARY_OP_INPLACE_POWER,
// TODO probably should rename these COMPARE->BINARY // these should return a bool
RT_COMPARE_OP_LESS, RT_BINARY_OP_LESS,
RT_COMPARE_OP_MORE, RT_BINARY_OP_MORE,
RT_COMPARE_OP_EQUAL, RT_BINARY_OP_EQUAL,
RT_COMPARE_OP_LESS_EQUAL, RT_BINARY_OP_LESS_EQUAL,
RT_COMPARE_OP_MORE_EQUAL, RT_BINARY_OP_MORE_EQUAL,
RT_COMPARE_OP_NOT_EQUAL, RT_BINARY_OP_NOT_EQUAL,
RT_COMPARE_OP_IN, RT_BINARY_OP_IN,
RT_COMPARE_OP_NOT_IN, RT_BINARY_OP_IS,
RT_COMPARE_OP_IS, RT_BINARY_OP_EXCEPTION_MATCH,
RT_COMPARE_OP_IS_NOT, // these are not supported by the runtime and must be synthesised by the emitter
RT_COMPARE_OP_EXCEPTION_MATCH, RT_BINARY_OP_NOT_IN,
RT_BINARY_OP_IS_NOT,
} rt_binary_op_t; } rt_binary_op_t;
typedef enum { typedef enum {

View File

@ -263,12 +263,14 @@ void mp_byte_code_print(const byte *ip, int len) {
printf("POP_EXCEPT"); printf("POP_EXCEPT");
break; break;
/* case MP_BC_NOT:
printf("NOT");
break;
case MP_BC_UNARY_OP: case MP_BC_UNARY_OP:
unum = *ip++; unum = *ip++;
*sp = rt_unary_op(unum, *sp); printf("UNARY_OP " UINT_FMT, unum);
break; break;
*/
case MP_BC_BINARY_OP: case MP_BC_BINARY_OP:
unum = *ip++; unum = *ip++;

View File

@ -428,6 +428,14 @@ unwind_jump:
//sp -= 3; // pop 3 exception values //sp -= 3; // pop 3 exception values
break; break;
case MP_BC_NOT:
if (TOP() == mp_const_true) {
SET_TOP(mp_const_false);
} else {
SET_TOP(mp_const_true);
}
break;
case MP_BC_UNARY_OP: case MP_BC_UNARY_OP:
unum = *ip++; unum = *ip++;
SET_TOP(rt_unary_op(unum, TOP())); SET_TOP(rt_unary_op(unum, TOP()));