Skip to content

Commit 1d24ea5

Browse files
committed
py: Finish implementation of all del opcodes.
At this point, all opcodes are now implemented! Some del opcodes have been combined with store opcodes, with the value to store being MP_OBJ_NULL.
1 parent 134c10e commit 1d24ea5

9 files changed

Lines changed: 61 additions & 36 deletions

File tree

py/bc0.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
// Micro Python byte-codes.
22
// The comment at the end of the line (if it exists) tells the arguments to the byte-code.
33

4+
// TODO Add MP_BC_LOAD_FAST_CHECKED and MP_BC_STORE_FAST_CHECKED for acting on those
5+
// locals which have del called on them anywhere in the function.
6+
// UnboundLocalError: local variable '%s' referenced before assignment
7+
48
#define MP_BC_LOAD_CONST_FALSE (0x10)
59
#define MP_BC_LOAD_CONST_NONE (0x11)
610
#define MP_BC_LOAD_CONST_TRUE (0x12)
@@ -34,12 +38,9 @@
3438
#define MP_BC_STORE_ATTR (0x37) // qstr
3539
#define MP_BC_STORE_SUBSCR (0x38)
3640

37-
#define MP_BC_DELETE_FAST_N (0x39) // uint
38-
#define MP_BC_DELETE_DEREF (0x3a) // uint
39-
#define MP_BC_DELETE_NAME (0x3b) // qstr
40-
#define MP_BC_DELETE_GLOBAL (0x3c) // qstr
41-
#define MP_BC_DELETE_ATTR (0x3d) // qstr
42-
#define MP_BC_DELETE_SUBSCR (0x3e)
41+
#define MP_BC_DELETE_NAME (0x39) // qstr
42+
#define MP_BC_DELETE_GLOBAL (0x3a) // qstr
43+
#define MP_BC_DELETE_SUBSCR (0x3b)
4344

4445
#define MP_BC_DUP_TOP (0x40)
4546
#define MP_BC_DUP_TOP_TWO (0x41)
@@ -97,4 +98,3 @@
9798
#define MP_BC_IMPORT_NAME (0xe0) // qstr
9899
#define MP_BC_IMPORT_FROM (0xe1) // qstr
99100
#define MP_BC_IMPORT_STAR (0xe2)
100-

py/emitbc.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ struct _emit_t {
3636
byte dummy_data[8];
3737
};
3838

39+
STATIC void emit_bc_rot_two(emit_t *emit);
40+
3941
emit_t *emit_bc_new(uint max_num_labels) {
4042
emit_t *emit = m_new0(emit_t, 1);
4143
emit->max_num_labels = max_num_labels;
@@ -487,14 +489,13 @@ STATIC void emit_bc_store_subscr(emit_t *emit) {
487489
}
488490

489491
STATIC void emit_bc_delete_fast(emit_t *emit, qstr qstr, int local_num) {
490-
assert(local_num >= 0);
491-
emit_bc_pre(emit, 0);
492-
emit_write_byte_code_byte_uint(emit, MP_BC_DELETE_FAST_N, local_num);
492+
emit_bc_load_null(emit);
493+
emit_bc_store_fast(emit, qstr, local_num);
493494
}
494495

495496
STATIC void emit_bc_delete_deref(emit_t *emit, qstr qstr, int local_num) {
496-
emit_bc_pre(emit, 0);
497-
emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_DEREF, local_num);
497+
emit_bc_load_null(emit);
498+
emit_bc_store_deref(emit, qstr, local_num);
498499
}
499500

500501
STATIC void emit_bc_delete_name(emit_t *emit, qstr qstr) {
@@ -508,8 +509,9 @@ STATIC void emit_bc_delete_global(emit_t *emit, qstr qstr) {
508509
}
509510

510511
STATIC void emit_bc_delete_attr(emit_t *emit, qstr qstr) {
511-
emit_bc_pre(emit, -1);
512-
emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_ATTR, qstr);
512+
emit_bc_load_null(emit);
513+
emit_bc_rot_two(emit);
514+
emit_bc_store_attr(emit, qstr);
513515
}
514516

515517
STATIC void emit_bc_delete_subscr(emit_t *emit) {

py/obj.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ struct _mp_obj_type_t {
217217
mp_binary_op_fun_t binary_op; // can return NULL if op not supported
218218

219219
mp_load_attr_fun_t load_attr;
220-
mp_store_attr_fun_t store_attr;
220+
mp_store_attr_fun_t store_attr; // if value is MP_OBJ_NULL, then delete that attribute
221221
// Implements container[index] = val; note that load_item is implemented
222222
// by binary_op(RT_BINARY_OP_SUBSCR)
223223
mp_store_item_fun_t store_item;

py/objmodule.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,14 @@ STATIC void module_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
2727

2828
STATIC bool module_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
2929
mp_obj_module_t *self = self_in;
30-
// TODO CPython allows STORE_ATTR to a module, but is this the correct implementation?
31-
mp_obj_dict_store(self->globals, MP_OBJ_NEW_QSTR(attr), value);
30+
if (value == MP_OBJ_NULL) {
31+
// delete attribute
32+
mp_obj_dict_delete(self->globals, MP_OBJ_NEW_QSTR(attr));
33+
} else {
34+
// store attribute
35+
// TODO CPython allows STORE_ATTR to a module, but is this the correct implementation?
36+
mp_obj_dict_store(self->globals, MP_OBJ_NEW_QSTR(attr), value);
37+
}
3238
return true;
3339
}
3440

py/objtype.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,15 @@ STATIC void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
257257

258258
STATIC bool class_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
259259
mp_obj_class_t *self = self_in;
260-
mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
261-
return true;
260+
if (value == MP_OBJ_NULL) {
261+
// delete attribute
262+
mp_map_elem_t *el = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
263+
return el != NULL;
264+
} else {
265+
// store attribute
266+
mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
267+
return true;
268+
}
262269
}
263270

264271
bool class_store_item(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
@@ -356,11 +363,19 @@ STATIC bool type_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
356363
if (self->locals_dict != NULL) {
357364
assert(MP_OBJ_IS_TYPE(self->locals_dict, &mp_type_dict)); // Micro Python restriction, for now
358365
mp_map_t *locals_map = mp_obj_dict_get_map(self->locals_dict);
359-
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
360-
// note that locals_map may be in ROM, so add will fail in that case
361-
if (elem != NULL) {
362-
elem->value = value;
363-
return true;
366+
if (value == MP_OBJ_NULL) {
367+
// delete attribute
368+
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
369+
// note that locals_map may be in ROM, so remove will fail in that case
370+
return elem != NULL;
371+
} else {
372+
// store attribute
373+
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
374+
// note that locals_map may be in ROM, so add will fail in that case
375+
if (elem != NULL) {
376+
elem->value = value;
377+
return true;
378+
}
364379
}
365380
}
366381

py/runtime.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,21 @@ void mp_store_name(qstr qstr, mp_obj_t obj) {
132132

133133
void mp_delete_name(qstr qstr) {
134134
DEBUG_OP_printf("delete name %s\n", qstr_str(qstr));
135-
// TODO raise NameError if qstr not found
136-
mp_map_lookup(&dict_locals->map, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
135+
// TODO convert KeyError to NameError if qstr not found
136+
mp_obj_dict_delete(dict_locals, MP_OBJ_NEW_QSTR(qstr));
137137
}
138138

139139
void mp_store_global(qstr qstr, mp_obj_t obj) {
140140
DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qstr), obj);
141141
mp_obj_dict_store(dict_globals, MP_OBJ_NEW_QSTR(qstr), obj);
142142
}
143143

144+
void mp_delete_global(qstr qstr) {
145+
DEBUG_OP_printf("delete global %s\n", qstr_str(qstr));
146+
// TODO convert KeyError to NameError if qstr not found
147+
mp_obj_dict_delete(dict_globals, MP_OBJ_NEW_QSTR(qstr));
148+
}
149+
144150
mp_obj_t mp_unary_op(int op, mp_obj_t arg) {
145151
DEBUG_OP_printf("unary %d %p\n", op, arg);
146152

py/runtime.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ mp_obj_t mp_load_build_class(void);
2020
void mp_store_name(qstr qstr, mp_obj_t obj);
2121
void mp_store_global(qstr qstr, mp_obj_t obj);
2222
void mp_delete_name(qstr qstr);
23+
void mp_delete_global(qstr qstr);
2324

2425
mp_obj_t mp_unary_op(int op, mp_obj_t arg);
2526
mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs);

py/showbc.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,6 @@ void mp_byte_code_print(const byte *ip, int len) {
193193
printf("STORE_SUBSCR");
194194
break;
195195

196-
case MP_BC_DELETE_FAST_N:
197-
DECODE_UINT;
198-
printf("DELETE_FAST_N " UINT_FMT, unum);
199-
break;
200-
201196
case MP_BC_DELETE_NAME:
202197
DECODE_QSTR;
203198
printf("DELETE_NAME %s", qstr_str(qstr));

py/vm.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -314,16 +314,16 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i
314314
sp -= 3;
315315
break;
316316

317-
case MP_BC_DELETE_FAST_N:
318-
DECODE_UINT;
319-
fastn[-unum] = MP_OBJ_NULL;
320-
break;
321-
322317
case MP_BC_DELETE_NAME:
323318
DECODE_QSTR;
324319
mp_delete_name(qst);
325320
break;
326321

322+
case MP_BC_DELETE_GLOBAL:
323+
DECODE_QSTR;
324+
mp_delete_global(qst);
325+
break;
326+
327327
case MP_BC_DELETE_SUBSCR:
328328
mp_delete_subscr(sp[-1], sp[0]);
329329
sp -= 2;

0 commit comments

Comments
 (0)