Skip to content

Commit 4d9cad1

Browse files
committed
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.
1 parent a3cf4ea commit 4d9cad1

3 files changed

Lines changed: 47 additions & 9 deletions

File tree

py/emitnative.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,10 +1424,17 @@ STATIC void emit_native_load_subscr(emit_t *emit) {
14241424
vtype_kind_t vtype_base = peek_vtype(emit, 1);
14251425

14261426
if (vtype_base == VTYPE_PYOBJ) {
1427-
// standard Python call
1428-
vtype_kind_t vtype_index;
1429-
emit_pre_pop_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1);
1430-
assert(vtype_index == VTYPE_PYOBJ);
1427+
// standard Python subscr
1428+
// TODO factor this implicit cast code with other uses of it
1429+
vtype_kind_t vtype_index = peek_vtype(emit, 0);
1430+
if (vtype_index == VTYPE_PYOBJ) {
1431+
emit_pre_pop_reg(emit, &vtype_index, REG_ARG_2);
1432+
} else {
1433+
emit_pre_pop_reg(emit, &vtype_index, REG_ARG_1);
1434+
emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, vtype_index, REG_ARG_2); // arg2 = type
1435+
ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_RET);
1436+
}
1437+
emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1);
14311438
emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, (mp_uint_t)MP_OBJ_SENTINEL, REG_ARG_3);
14321439
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
14331440
} else {
@@ -1599,11 +1606,16 @@ STATIC void emit_native_store_subscr(emit_t *emit) {
15991606
vtype_kind_t vtype_base = peek_vtype(emit, 1);
16001607

16011608
if (vtype_base == VTYPE_PYOBJ) {
1602-
// standard Python call
1603-
vtype_kind_t vtype_index, vtype_value;
1609+
// standard Python subscr
1610+
vtype_kind_t vtype_index = peek_vtype(emit, 0);
1611+
vtype_kind_t vtype_value = peek_vtype(emit, 2);
1612+
if (vtype_index != VTYPE_PYOBJ || vtype_value != VTYPE_PYOBJ) {
1613+
// need to implicitly convert non-objects to objects
1614+
// TODO do this properly
1615+
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, 3);
1616+
adjust_stack(emit, 3);
1617+
}
16041618
emit_pre_pop_reg_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1, &vtype_value, REG_ARG_3);
1605-
assert(vtype_index == VTYPE_PYOBJ);
1606-
assert(vtype_value == VTYPE_PYOBJ);
16071619
emit_call(emit, MP_F_OBJ_SUBSCR);
16081620
} else {
16091621
// viper store
@@ -2081,7 +2093,9 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
20812093
emit_post_push_reg(emit, VTYPE_BOOL, REG_RET);
20822094
} else {
20832095
// TODO other ops not yet implemented
2084-
assert(0);
2096+
adjust_stack(emit, 1);
2097+
EMIT_NATIVE_VIPER_TYPE_ERROR(emit,
2098+
"binary op %q not implemented", mp_binary_op_method_name[op]);
20852099
}
20862100
} else if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) {
20872101
emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_3, &vtype_lhs, REG_ARG_2);

tests/micropython/viper_subscr.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# test standard Python subscr using viper types
2+
3+
@micropython.viper
4+
def get(dest, i:int):
5+
i += 1
6+
return dest[i]
7+
8+
@micropython.viper
9+
def set(dest, i:int, val:int):
10+
i += 1
11+
dest[i] = val + 1
12+
13+
ar = [i for i in range(3)]
14+
15+
for i in range(len(ar)):
16+
set(ar, i - 1, i)
17+
print(ar)
18+
19+
for i in range(len(ar)):
20+
print(get(ar, i - 1))
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[1, 2, 3]
2+
1
3+
2
4+
3

0 commit comments

Comments
 (0)