From b8698fca75018b5cacaf9b2fdfd821f86b8acaf4 Mon Sep 17 00:00:00 2001 From: "John R. Lenton" Date: Sat, 11 Jan 2014 00:58:59 +0000 Subject: [PATCH] unified the bops --- py/bc0.h | 1 - py/compile.c | 26 +++++----- py/emit.h | 1 - py/emitbc.c | 6 --- py/emitcpy.c | 10 ---- py/emitnative.c | 26 ---------- py/emitpass1.c | 1 - py/obj.h | 2 +- py/objfloat.c | 6 +++ py/objlist.c | 4 +- py/runtime.c | 125 ++++++++++++++++-------------------------------- py/runtime.h | 1 - py/runtime0.h | 6 +-- py/showbc.c | 5 -- py/vm.c | 7 --- 15 files changed, 64 insertions(+), 163 deletions(-) diff --git a/py/bc0.h b/py/bc0.h index 0a4a49ce66..9329f21784 100644 --- a/py/bc0.h +++ b/py/bc0.h @@ -66,7 +66,6 @@ #define MP_BC_UNARY_OP (0x60) // byte #define MP_BC_BINARY_OP (0x61) // byte -#define MP_BC_COMPARE_OP (0x62) // byte #define MP_BC_BUILD_TUPLE (0x70) // uint #define MP_BC_BUILD_LIST (0x71) // uint diff --git a/py/compile.c b/py/compile.c index 7e92d4b4cc..2e22d64262 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1464,9 +1464,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_end); if (MP_PARSE_NODE_LEAF_ARG(pn_step) >= 0) { - EMIT(compare_op, RT_COMPARE_OP_LESS); + EMIT(binary_op, RT_COMPARE_OP_LESS); } else { - EMIT(compare_op, RT_COMPARE_OP_MORE); + EMIT(binary_op, RT_COMPARE_OP_MORE); } EMIT(pop_jump_if_true, top_label); @@ -1610,7 +1610,7 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except, } EMIT(dup_top); compile_node(comp, pns_exception_expr); - EMIT(compare_op, RT_COMPARE_OP_EXCEPTION_MATCH); + EMIT(binary_op, RT_COMPARE_OP_EXCEPTION_MATCH); EMIT(pop_jump_if_false, end_finally_label); } @@ -1925,29 +1925,29 @@ void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) { EMIT(rot_three); } if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_LESS)) { - EMIT(compare_op, RT_COMPARE_OP_LESS); + EMIT(binary_op, RT_COMPARE_OP_LESS); } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MORE)) { - EMIT(compare_op, RT_COMPARE_OP_MORE); + EMIT(binary_op, RT_COMPARE_OP_MORE); } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_EQUAL)) { - EMIT(compare_op, RT_COMPARE_OP_EQUAL); + EMIT(binary_op, RT_COMPARE_OP_EQUAL); } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_LESS_EQUAL)) { - EMIT(compare_op, RT_COMPARE_OP_LESS_EQUAL); + EMIT(binary_op, RT_COMPARE_OP_LESS_EQUAL); } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MORE_EQUAL)) { - EMIT(compare_op, RT_COMPARE_OP_MORE_EQUAL); + EMIT(binary_op, RT_COMPARE_OP_MORE_EQUAL); } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_NOT_EQUAL)) { - EMIT(compare_op, RT_COMPARE_OP_NOT_EQUAL); + EMIT(binary_op, RT_COMPARE_OP_NOT_EQUAL); } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_KW_IN)) { - EMIT(compare_op, RT_COMPARE_OP_IN); + EMIT(binary_op, RT_COMPARE_OP_IN); } else if (MP_PARSE_NODE_IS_STRUCT(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); if (kind == PN_comp_op_not_in) { - EMIT(compare_op, RT_COMPARE_OP_NOT_IN); + EMIT(binary_op, RT_COMPARE_OP_NOT_IN); } else if (kind == PN_comp_op_is) { if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) { - EMIT(compare_op, RT_COMPARE_OP_IS); + EMIT(binary_op, RT_COMPARE_OP_IS); } else { - EMIT(compare_op, RT_COMPARE_OP_IS_NOT); + EMIT(binary_op, RT_COMPARE_OP_IS_NOT); } } else { // shouldn't happen diff --git a/py/emit.h b/py/emit.h index 66e87fd4c6..fd41764d40 100644 --- a/py/emit.h +++ b/py/emit.h @@ -85,7 +85,6 @@ typedef struct _emit_method_table_t { void (*pop_except)(emit_t *emit); void (*unary_op)(emit_t *emit, rt_unary_op_t op); void (*binary_op)(emit_t *emit, rt_binary_op_t op); - void (*compare_op)(emit_t *emit, rt_compare_op_t op); void (*build_tuple)(emit_t *emit, int n_args); void (*build_list)(emit_t *emit, int n_args); void (*list_append)(emit_t *emit, int list_stack_index); diff --git a/py/emitbc.c b/py/emitbc.c index c0ec2469a6..5da408c3e5 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -531,11 +531,6 @@ static void emit_bc_binary_op(emit_t *emit, rt_binary_op_t op) { emit_write_byte_1_byte(emit, MP_BC_BINARY_OP, op); } -static void emit_bc_compare_op(emit_t *emit, rt_compare_op_t op) { - emit_pre(emit, -1); - emit_write_byte_1_byte(emit, MP_BC_COMPARE_OP, op); -} - static void emit_bc_build_tuple(emit_t *emit, int n_args) { assert(n_args >= 0); emit_pre(emit, 1 - n_args); @@ -762,7 +757,6 @@ const emit_method_table_t emit_bc_method_table = { emit_bc_pop_except, emit_bc_unary_op, emit_bc_binary_op, - emit_bc_compare_op, emit_bc_build_tuple, emit_bc_build_list, emit_bc_list_append, diff --git a/py/emitcpy.c b/py/emitcpy.c index 7b2d50fb7e..dfc851d2ed 100644 --- a/py/emitcpy.c +++ b/py/emitcpy.c @@ -579,15 +579,6 @@ 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_MODULO: printf("INPLACE_MODULO\n"); break; case RT_BINARY_OP_INPLACE_POWER: printf("INPLACE_POWER\n"); break; - default: assert(0); - } - } -} - -static void emit_cpy_compare_op(emit_t *emit, rt_compare_op_t op) { - emit_pre(emit, -1, 3); - if (emit->pass == PASS_3) { - switch (op) { case RT_COMPARE_OP_LESS: printf("COMPARE_OP <\n"); break; case RT_COMPARE_OP_MORE: printf("COMPARE_OP >\n"); break; case RT_COMPARE_OP_EQUAL: printf("COMPARE_OP ==\n"); break; @@ -863,7 +854,6 @@ const emit_method_table_t emit_cpython_method_table = { emit_cpy_pop_except, emit_cpy_unary_op, emit_cpy_binary_op, - emit_cpy_compare_op, emit_cpy_build_tuple, emit_cpy_build_list, emit_cpy_list_append, diff --git a/py/emitnative.c b/py/emitnative.c index cc00c57319..8a6bd8f2d0 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -1013,31 +1013,6 @@ static void emit_native_binary_op(emit_t *emit, rt_binary_op_t op) { } } -static void emit_native_compare_op(emit_t *emit, rt_compare_op_t op) { - vtype_kind_t vtype_lhs, vtype_rhs; - emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_3, &vtype_lhs, REG_ARG_2); - if (vtype_lhs == VTYPE_INT && vtype_rhs == VTYPE_INT) { - assert(op == RT_COMPARE_OP_LESS); -#if N_X64 - 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_setcc_r8(emit->as, JCC_JL, REG_RET); -#elif N_THUMB - asm_thumb_cmp_reg_reg(emit->as, REG_ARG_2, REG_ARG_3); - asm_thumb_ite_ge(emit->as); - asm_thumb_movs_rlo_i8(emit->as, REG_RET, 0); // if r0 >= r1 - asm_thumb_movs_rlo_i8(emit->as, REG_RET, 1); // if r0 < r1 -#endif - emit_post_push_reg(emit, VTYPE_BOOL, REG_RET); - } else if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) { - emit_call_with_imm_arg(emit, RT_F_COMPARE_OP, rt_compare_op, op, REG_ARG_1); - emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); - } else { - printf("ViperTypeError: can't do comparison between types %d and %d\n", vtype_lhs, vtype_rhs); - assert(0); - } -} - static void emit_native_build_tuple(emit_t *emit, int n_args) { // for viper: call runtime, with types of args // if wrapped in byte_array, or something, allocates memory and fills it @@ -1297,7 +1272,6 @@ const emit_method_table_t EXPORT_FUN(method_table) = { emit_native_pop_except, emit_native_unary_op, emit_native_binary_op, - emit_native_compare_op, emit_native_build_tuple, emit_native_build_list, emit_native_list_append, diff --git a/py/emitpass1.c b/py/emitpass1.c index f78ec7e27e..2f0ecac86d 100644 --- a/py/emitpass1.c +++ b/py/emitpass1.c @@ -187,5 +187,4 @@ const emit_method_table_t emit_pass1_method_table = { (void*)emit_pass1_dummy, (void*)emit_pass1_dummy, (void*)emit_pass1_dummy, - (void*)emit_pass1_dummy, }; diff --git a/py/obj.h b/py/obj.h index d897d906d9..8d236008ee 100644 --- a/py/obj.h +++ b/py/obj.h @@ -155,7 +155,6 @@ struct _mp_obj_type_t { /* What we might need to add here: - compare_op store_subscr list dict len str tuple list map @@ -241,6 +240,7 @@ extern const mp_obj_type_t none_type; // bool extern const mp_obj_type_t bool_type; +#define MP_BOOL(x) (x ? mp_const_true : mp_const_false) // cell mp_obj_t mp_obj_cell_get(mp_obj_t self_in); diff --git a/py/objfloat.c b/py/objfloat.c index 283285b07f..bb44ac9549 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -99,6 +99,12 @@ 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_INPLACE_TRUE_DIVIDE: lhs_val /= rhs_val; break; + + case RT_COMPARE_OP_LESS: return MP_BOOL(lhs_val < rhs_val); + case RT_COMPARE_OP_MORE: return MP_BOOL(lhs_val > rhs_val); + case RT_COMPARE_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val); + case RT_COMPARE_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val); + return NULL; // op not supported } return mp_obj_new_float(lhs_val); diff --git a/py/objlist.c b/py/objlist.c index ce55aa5100..7d0402d286 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -143,8 +143,8 @@ static void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, bool r mp_obj_t *t = tail; mp_obj_t v = key_fn == NULL ? tail[0] : rt_call_function_1(key_fn, tail[0]); // get pivot using key_fn for (;;) { - do ++h; while (rt_compare_op(op, key_fn == NULL ? h[0] : rt_call_function_1(key_fn, h[0]), v) == mp_const_true); - do --t; while (h < t && rt_compare_op(op, v, key_fn == NULL ? t[0] : rt_call_function_1(key_fn, t[0])) == mp_const_true); + do ++h; while (rt_binary_op(op, key_fn == NULL ? h[0] : rt_call_function_1(key_fn, h[0]), v) == mp_const_true); + do --t; while (h < t && rt_binary_op(op, v, key_fn == NULL ? t[0] : rt_call_function_1(key_fn, t[0])) == mp_const_true); if (h >= t) break; mp_obj_t x = h[0]; h[0] = t[0]; diff --git a/py/runtime.c b/py/runtime.c index 3ec47a9ed5..53861f1e40 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -514,6 +514,10 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { lhs_val = ans; break; } + case RT_COMPARE_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_COMPARE_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; default: assert(0); } @@ -525,12 +529,43 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { } else if (MP_OBJ_IS_TYPE(rhs, &complex_type)) { return mp_obj_complex_binary_op(op, lhs_val, 0, rhs); } - } else if (MP_OBJ_IS_OBJ(lhs)) { - mp_obj_base_t *o = lhs; - if (o->type->binary_op != NULL) { - mp_obj_t result = o->type->binary_op(op, lhs, rhs); - if (result != NULL) { - return result; + } else { + // deal with == and != + if (op == RT_COMPARE_OP_EQUAL || op == RT_COMPARE_OP_NOT_EQUAL) { + if (mp_obj_equal(lhs, rhs)) { + if (op == RT_COMPARE_OP_EQUAL) { + return mp_const_true; + } else { + return mp_const_false; + } + } else { + if (op == RT_COMPARE_OP_EQUAL) { + return mp_const_false; + } else { + return mp_const_true; + } + } + } + + // deal with exception_match + if (op == RT_COMPARE_OP_EXCEPTION_MATCH) { + // 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_exception_get_type(lhs) == mp_obj_exception_get_type(rhs)) { + return mp_const_true; + } else { + return mp_const_false; + } + } + } + + if (MP_OBJ_IS_OBJ(lhs)) { + mp_obj_base_t *o = lhs; + if (o->type->binary_op != NULL) { + mp_obj_t result = o->type->binary_op(op, lhs, rhs); + if (result != NULL) { + return result; + } } } } @@ -541,83 +576,6 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs))); } -mp_obj_t rt_compare_op(int op, mp_obj_t lhs, mp_obj_t rhs) { - DEBUG_OP_printf("compare %d %p %p\n", op, lhs, rhs); - - // deal with == and != - if (op == RT_COMPARE_OP_EQUAL || op == RT_COMPARE_OP_NOT_EQUAL) { - if (mp_obj_equal(lhs, rhs)) { - if (op == RT_COMPARE_OP_EQUAL) { - return mp_const_true; - } else { - return mp_const_false; - } - } else { - if (op == RT_COMPARE_OP_EQUAL) { - return mp_const_false; - } else { - return mp_const_true; - } - } - } - - // deal with exception_match - if (op == RT_COMPARE_OP_EXCEPTION_MATCH) { - // 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_exception_get_type(lhs) == mp_obj_exception_get_type(rhs)) { - return mp_const_true; - } else { - return mp_const_false; - } - } - } - - // deal with small ints - if (MP_OBJ_IS_SMALL_INT(lhs) && MP_OBJ_IS_SMALL_INT(rhs)) { - mp_small_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs); - mp_small_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs); - int cmp; - switch (op) { - case RT_COMPARE_OP_LESS: cmp = lhs_val < rhs_val; break; - case RT_COMPARE_OP_MORE: cmp = lhs_val > rhs_val; break; - case RT_COMPARE_OP_LESS_EQUAL: cmp = lhs_val <= rhs_val; break; - case RT_COMPARE_OP_MORE_EQUAL: cmp = lhs_val >= rhs_val; break; - default: assert(0); cmp = 0; - } - if (cmp) { - return mp_const_true; - } else { - return mp_const_false; - } - } - -#if MICROPY_ENABLE_FLOAT - // deal with floats - if (MP_OBJ_IS_TYPE(lhs, &float_type) || MP_OBJ_IS_TYPE(rhs, &float_type)) { - mp_float_t lhs_val = mp_obj_get_float(lhs); - mp_float_t rhs_val = mp_obj_get_float(rhs); - int cmp; - switch (op) { - case RT_COMPARE_OP_LESS: cmp = lhs_val < rhs_val; break; - case RT_COMPARE_OP_MORE: cmp = lhs_val > rhs_val; break; - case RT_COMPARE_OP_LESS_EQUAL: cmp = lhs_val <= rhs_val; break; - case RT_COMPARE_OP_MORE_EQUAL: cmp = lhs_val >= rhs_val; break; - default: assert(0); cmp = 0; - } - if (cmp) { - return mp_const_true; - } else { - return mp_const_false; - } - } -#endif - - // not implemented - assert(0); - return mp_const_none; -} - mp_obj_t rt_make_function_from_id(int unique_code_id) { DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id); if (unique_code_id < 1 || unique_code_id >= next_unique_code_id) { @@ -956,7 +914,6 @@ void *const rt_fun_table[RT_F_NUMBER_OF] = { rt_call_function_n, rt_call_method_n, rt_binary_op, - rt_compare_op, rt_getiter, rt_iternext, }; diff --git a/py/runtime.h b/py/runtime.h index 96f1671f67..ac53e14110 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -11,7 +11,6 @@ void rt_store_name(qstr qstr, mp_obj_t obj); 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_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs); -mp_obj_t rt_compare_op(int op, mp_obj_t lhs, mp_obj_t rhs); mp_obj_t rt_make_function_from_id(int unique_code_id); mp_obj_t rt_make_function_0(mp_fun_0_t f); mp_obj_t rt_make_function_1(mp_fun_1_t f); diff --git a/py/runtime0.h b/py/runtime0.h index 97dbe5ddbc..641fdaa9c6 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -31,9 +31,6 @@ typedef enum { RT_BINARY_OP_INPLACE_TRUE_DIVIDE, RT_BINARY_OP_INPLACE_MODULO, RT_BINARY_OP_INPLACE_POWER, -} rt_binary_op_t; - -typedef enum { RT_COMPARE_OP_LESS, RT_COMPARE_OP_MORE, RT_COMPARE_OP_EQUAL, @@ -45,7 +42,7 @@ typedef enum { RT_COMPARE_OP_IS, RT_COMPARE_OP_IS_NOT, RT_COMPARE_OP_EXCEPTION_MATCH, -} rt_compare_op_t; +} rt_binary_op_t; typedef enum { RT_F_LOAD_CONST_DEC = 0, @@ -71,7 +68,6 @@ typedef enum { RT_F_CALL_FUNCTION_N, RT_F_CALL_METHOD_N, RT_F_BINARY_OP, - RT_F_COMPARE_OP, RT_F_GETITER, RT_F_ITERNEXT, RT_F_NUMBER_OF, diff --git a/py/showbc.c b/py/showbc.c index 4ea0dd77e6..2ba81df40d 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -266,11 +266,6 @@ void mp_show_byte_code(const byte *ip, int len) { printf("BINARY_OP " UINT_FMT, unum); break; - case MP_BC_COMPARE_OP: - unum = *ip++; - printf("COMPARE_OP " UINT_FMT, unum); - break; - case MP_BC_BUILD_TUPLE: DECODE_UINT; printf("BUILD_TUPLE " UINT_FMT, unum); diff --git a/py/vm.c b/py/vm.c index e2bb3de642..3b910505a5 100644 --- a/py/vm.c +++ b/py/vm.c @@ -355,13 +355,6 @@ bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t ** SET_TOP(rt_binary_op(unum, obj1, obj2)); break; - case MP_BC_COMPARE_OP: - unum = *ip++; - obj2 = POP(); - obj1 = TOP(); - SET_TOP(rt_compare_op(unum, obj1, obj2)); - break; - case MP_BC_BUILD_TUPLE: DECODE_UINT; obj1 = rt_build_tuple(unum, sp);