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.
This commit is contained in:
Damien George 2015-06-04 11:52:16 +01:00
parent a3cf4ea2f6
commit 4d9cad180d
3 changed files with 47 additions and 9 deletions

View File

@ -1424,10 +1424,17 @@ STATIC void emit_native_load_subscr(emit_t *emit) {
vtype_kind_t vtype_base = peek_vtype(emit, 1); vtype_kind_t vtype_base = peek_vtype(emit, 1);
if (vtype_base == VTYPE_PYOBJ) { if (vtype_base == VTYPE_PYOBJ) {
// standard Python call // standard Python subscr
vtype_kind_t vtype_index; // TODO factor this implicit cast code with other uses of it
emit_pre_pop_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1); vtype_kind_t vtype_index = peek_vtype(emit, 0);
assert(vtype_index == VTYPE_PYOBJ); 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_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); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
} else { } else {
@ -1599,11 +1606,16 @@ STATIC void emit_native_store_subscr(emit_t *emit) {
vtype_kind_t vtype_base = peek_vtype(emit, 1); vtype_kind_t vtype_base = peek_vtype(emit, 1);
if (vtype_base == VTYPE_PYOBJ) { if (vtype_base == VTYPE_PYOBJ) {
// standard Python call // standard Python subscr
vtype_kind_t vtype_index, vtype_value; 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); 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); emit_call(emit, MP_F_OBJ_SUBSCR);
} else { } else {
// viper store // 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); emit_post_push_reg(emit, VTYPE_BOOL, REG_RET);
} else { } else {
// TODO other ops not yet implemented // 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) { } 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); emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_3, &vtype_lhs, REG_ARG_2);

View File

@ -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))

View File

@ -0,0 +1,4 @@
[1, 2, 3]
1
2
3