From 4d9cad180dbaf25cdbb9dd0c54a637483db933a7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 4 Jun 2015 11:52:16 +0100 Subject: [PATCH] py: Implement implicit cast to obj for viper load/store index/value. This allows to do "ar[i]" and "ar[i] = val" in viper when ar is a Python object and i and/or val are native viper types (eg ints). Patch also includes tests for this feature. --- py/emitnative.c | 32 +++++++++++++++++++-------- tests/micropython/viper_subscr.py | 20 +++++++++++++++++ tests/micropython/viper_subscr.py.exp | 4 ++++ 3 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 tests/micropython/viper_subscr.py create mode 100644 tests/micropython/viper_subscr.py.exp diff --git a/py/emitnative.c b/py/emitnative.c index 74c5b98ef8..4a382a2736 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -1424,10 +1424,17 @@ STATIC void emit_native_load_subscr(emit_t *emit) { vtype_kind_t vtype_base = peek_vtype(emit, 1); if (vtype_base == VTYPE_PYOBJ) { - // standard Python call - vtype_kind_t vtype_index; - emit_pre_pop_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1); - assert(vtype_index == VTYPE_PYOBJ); + // standard Python subscr + // TODO factor this implicit cast code with other uses of it + vtype_kind_t vtype_index = peek_vtype(emit, 0); + if (vtype_index == VTYPE_PYOBJ) { + emit_pre_pop_reg(emit, &vtype_index, REG_ARG_2); + } else { + emit_pre_pop_reg(emit, &vtype_index, REG_ARG_1); + emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, vtype_index, REG_ARG_2); // arg2 = type + ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_RET); + } + emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, (mp_uint_t)MP_OBJ_SENTINEL, REG_ARG_3); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } else { @@ -1599,11 +1606,16 @@ STATIC void emit_native_store_subscr(emit_t *emit) { vtype_kind_t vtype_base = peek_vtype(emit, 1); if (vtype_base == VTYPE_PYOBJ) { - // standard Python call - vtype_kind_t vtype_index, vtype_value; + // standard Python subscr + vtype_kind_t vtype_index = peek_vtype(emit, 0); + vtype_kind_t vtype_value = peek_vtype(emit, 2); + if (vtype_index != VTYPE_PYOBJ || vtype_value != VTYPE_PYOBJ) { + // need to implicitly convert non-objects to objects + // TODO do this properly + emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, 3); + adjust_stack(emit, 3); + } emit_pre_pop_reg_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1, &vtype_value, REG_ARG_3); - assert(vtype_index == VTYPE_PYOBJ); - assert(vtype_value == VTYPE_PYOBJ); emit_call(emit, MP_F_OBJ_SUBSCR); } else { // viper store @@ -2081,7 +2093,9 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { emit_post_push_reg(emit, VTYPE_BOOL, REG_RET); } else { // TODO other ops not yet implemented - assert(0); + adjust_stack(emit, 1); + EMIT_NATIVE_VIPER_TYPE_ERROR(emit, + "binary op %q not implemented", mp_binary_op_method_name[op]); } } else if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) { emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_3, &vtype_lhs, REG_ARG_2); diff --git a/tests/micropython/viper_subscr.py b/tests/micropython/viper_subscr.py new file mode 100644 index 0000000000..2198ed7313 --- /dev/null +++ b/tests/micropython/viper_subscr.py @@ -0,0 +1,20 @@ +# test standard Python subscr using viper types + +@micropython.viper +def get(dest, i:int): + i += 1 + return dest[i] + +@micropython.viper +def set(dest, i:int, val:int): + i += 1 + dest[i] = val + 1 + +ar = [i for i in range(3)] + +for i in range(len(ar)): + set(ar, i - 1, i) +print(ar) + +for i in range(len(ar)): + print(get(ar, i - 1)) diff --git a/tests/micropython/viper_subscr.py.exp b/tests/micropython/viper_subscr.py.exp new file mode 100644 index 0000000000..e68032ce1e --- /dev/null +++ b/tests/micropython/viper_subscr.py.exp @@ -0,0 +1,4 @@ +[1, 2, 3] +1 +2 +3