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:
parent
a3cf4ea2f6
commit
4d9cad180d
|
@ -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);
|
||||||
|
|
|
@ -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))
|
|
@ -0,0 +1,4 @@
|
||||||
|
[1, 2, 3]
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
Loading…
Reference in New Issue