Skip to content

Commit f4c9b33

Browse files
committed
py: Remove DELETE_SUBSCR opcode, combine with STORE_SUBSCR.
This makes the runtime and object APIs more consistent. mp_store_subscr functionality now moved into objects (ie list and dict store_item).
1 parent 4671392 commit f4c9b33

File tree

12 files changed

+107
-40
lines changed

12 files changed

+107
-40
lines changed

py/bc0.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040

4141
#define MP_BC_DELETE_NAME (0x39) // qstr
4242
#define MP_BC_DELETE_GLOBAL (0x3a) // qstr
43-
#define MP_BC_DELETE_SUBSCR (0x3b)
4443

4544
#define MP_BC_DUP_TOP (0x40)
4645
#define MP_BC_DUP_TOP_TWO (0x41)

py/emitbc.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ struct _emit_t {
3737
};
3838

3939
STATIC void emit_bc_rot_two(emit_t *emit);
40+
STATIC void emit_bc_rot_three(emit_t *emit);
4041

4142
emit_t *emit_bc_new(uint max_num_labels) {
4243
emit_t *emit = m_new0(emit_t, 1);
@@ -515,8 +516,9 @@ STATIC void emit_bc_delete_attr(emit_t *emit, qstr qstr) {
515516
}
516517

517518
STATIC void emit_bc_delete_subscr(emit_t *emit) {
518-
emit_bc_pre(emit, -2);
519-
emit_write_byte_code_byte(emit, MP_BC_DELETE_SUBSCR);
519+
emit_bc_load_null(emit);
520+
emit_bc_rot_three(emit);
521+
emit_bc_store_subscr(emit);
520522
}
521523

522524
STATIC void emit_bc_dup_top(emit_t *emit) {

py/obj.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, uint n_args, uint n_kw, const mp
163163
typedef mp_obj_t (*mp_unary_op_fun_t)(int op, mp_obj_t);
164164
typedef mp_obj_t (*mp_binary_op_fun_t)(int op, mp_obj_t, mp_obj_t);
165165
typedef void (*mp_load_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest); // for fail, do nothing; for attr, dest[0] = value; for method, dest[0] = method, dest[1] = self
166-
typedef bool (*mp_store_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t value); // return true if store succeeded
167-
typedef bool (*mp_store_item_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); // return true if store succeeded
166+
typedef bool (*mp_store_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t value); // return true if store succeeded; if value==MP_OBJ_NULL then delete
167+
typedef bool (*mp_store_item_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); // return true if store succeeded; if value==MP_OBJ_NULL then delete
168168

169169
typedef struct _mp_method_t {
170170
qstr name;
@@ -218,8 +218,9 @@ struct _mp_obj_type_t {
218218

219219
mp_load_attr_fun_t load_attr;
220220
mp_store_attr_fun_t store_attr; // if value is MP_OBJ_NULL, then delete that attribute
221-
// Implements container[index] = val; note that load_item is implemented
222-
// by binary_op(RT_BINARY_OP_SUBSCR)
221+
222+
// Implements container[index] = val. If val == MP_OBJ_NULL, then it's a delete.
223+
// Note that load_item is implemented by binary_op(RT_BINARY_OP_SUBSCR)
223224
mp_store_item_fun_t store_item;
224225

225226
mp_fun_1_t getiter;

py/objarray.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) {
143143
STATIC MP_DEFINE_CONST_FUN_OBJ_2(array_append_obj, array_append);
144144

145145
STATIC bool array_store_item(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
146+
if (value == MP_OBJ_NULL) {
147+
// delete item; does this need to be implemented?
148+
return false;
149+
}
146150
mp_obj_array_t *o = self_in;
147151
uint index = mp_get_index(o->base.type, o->len, index_in, false);
148152
mp_binary_set_val(o->typecode, o->items, index, value);

py/objdict.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,14 @@ STATIC mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
114114
}
115115
}
116116

117+
STATIC bool dict_store_item(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
118+
if (value == MP_OBJ_NULL) {
119+
mp_obj_dict_delete(self_in, index);
120+
} else {
121+
mp_obj_dict_store(self_in, index, value);
122+
}
123+
return true;
124+
}
117125

118126
/******************************************************************************/
119127
/* dict iterator */
@@ -484,6 +492,7 @@ const mp_obj_type_t mp_type_dict = {
484492
.make_new = dict_make_new,
485493
.unary_op = dict_unary_op,
486494
.binary_op = dict_binary_op,
495+
.store_item = dict_store_item,
487496
.getiter = dict_getiter,
488497
.locals_dict = (mp_obj_t)&dict_locals_dict,
489498
};

py/objlist.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ typedef struct _mp_obj_list_t {
1919
STATIC mp_obj_t mp_obj_new_list_iterator(mp_obj_list_t *list, int cur);
2020
STATIC mp_obj_list_t *list_new(uint n);
2121
STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in);
22+
STATIC mp_obj_t list_pop(uint n_args, const mp_obj_t *args);
2223

2324
// TODO: Move to mpconfig.h
2425
#define LIST_MIN_ALLOC 4
@@ -146,6 +147,16 @@ STATIC mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
146147
}
147148
}
148149

150+
STATIC bool list_store_item(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
151+
if (value == MP_OBJ_NULL) {
152+
mp_obj_t args[2] = {self_in, index};
153+
list_pop(2, args);
154+
} else {
155+
mp_obj_list_store(self_in, index, value);
156+
}
157+
return true;
158+
}
159+
149160
STATIC mp_obj_t list_getiter(mp_obj_t o_in) {
150161
return mp_obj_new_list_iterator(o_in, 0);
151162
}
@@ -349,6 +360,7 @@ const mp_obj_type_t mp_type_list = {
349360
.make_new = list_make_new,
350361
.unary_op = list_unary_op,
351362
.binary_op = list_binary_op,
363+
.store_item = list_store_item,
352364
.getiter = list_getiter,
353365
.locals_dict = (mp_obj_t)&list_locals_dict,
354366
};

py/objtype.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,11 @@ STATIC bool class_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
269269
}
270270

271271
bool class_store_item(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
272+
if (value == MP_OBJ_NULL) {
273+
// delete item
274+
// TODO implement me!
275+
return false;
276+
}
272277
mp_obj_class_t *self = self_in;
273278
mp_obj_t member = mp_obj_class_lookup(self->base.type, MP_QSTR___setitem__);
274279
if (member != MP_OBJ_NULL) {

py/runtime.c

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -841,37 +841,18 @@ void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) {
841841

842842
void mp_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) {
843843
DEBUG_OP_printf("store subscr %p[%p] <- %p\n", base, index, value);
844-
if (MP_OBJ_IS_TYPE(base, &mp_type_list)) {
845-
// list store
846-
mp_obj_list_store(base, index, value);
847-
} else if (MP_OBJ_IS_TYPE(base, &mp_type_dict)) {
848-
// dict store
849-
mp_obj_dict_store(base, index, value);
850-
} else {
851-
mp_obj_type_t *type = mp_obj_get_type(base);
852-
if (type->store_item != NULL) {
853-
bool r = type->store_item(base, index, value);
854-
if (r) {
855-
return;
856-
}
857-
// TODO: call base classes here?
844+
mp_obj_type_t *type = mp_obj_get_type(base);
845+
if (type->store_item != NULL) {
846+
bool r = type->store_item(base, index, value);
847+
if (r) {
848+
return;
858849
}
859-
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item assignment", mp_obj_get_type_str(base)));
850+
// TODO: call base classes here?
860851
}
861-
}
862-
863-
void mp_delete_subscr(mp_obj_t base, mp_obj_t index) {
864-
DEBUG_OP_printf("delete subscr %p[%p]\n", base, index);
865-
/* list delete not implemented
866-
if (MP_OBJ_IS_TYPE(base, &mp_type_list)) {
867-
// list delete
868-
mp_obj_list_delete(base, index);
869-
} else */
870-
if (MP_OBJ_IS_TYPE(base, &mp_type_dict)) {
871-
// dict delete
872-
mp_obj_dict_delete(base, index);
873-
} else {
852+
if (value == MP_OBJ_NULL) {
874853
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item deletion", mp_obj_get_type_str(base)));
854+
} else {
855+
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item assignment", mp_obj_get_type_str(base)));
875856
}
876857
}
877858

py/vm.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -324,11 +324,6 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i
324324
mp_delete_global(qst);
325325
break;
326326

327-
case MP_BC_DELETE_SUBSCR:
328-
mp_delete_subscr(sp[-1], sp[0]);
329-
sp -= 2;
330-
break;
331-
332327
case MP_BC_DUP_TOP:
333328
obj1 = TOP();
334329
PUSH(obj1);

tests/basics/del-attr.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# del a class attribute
2+
3+
del C.f
4+
try:
5+
print(C.x)
6+
except AttributeError:
7+
print("AttributeError")
8+
try:
9+
del C.f
10+
except AttributeError:
11+
print("AttributeError")
12+
13+
# del an instance attribute
14+
15+
c = C()
16+
17+
c.x = 1
18+
print(c.x)
19+
20+
del c.x
21+
try:
22+
print(c.x)
23+
except AttributeError:
24+
print("AttributeError")
25+
try:
26+
del c.x
27+
except AttributeError:
28+
print("AttributeError")

0 commit comments

Comments
 (0)