Skip to content

Commit 729f7b4

Browse files
committed
py: Merge BINARY_OP_SUBSCR and store_subscr (w/ delete) into subscr.
mp_obj_t->subscr now does load/store/delete.
1 parent de7c425 commit 729f7b4

24 files changed

Lines changed: 206 additions & 148 deletions

py/bc0.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#define MP_BC_LOAD_ATTR (0x28) // qstr
2424
#define MP_BC_LOAD_METHOD (0x29) // qstr
2525
#define MP_BC_LOAD_BUILD_CLASS (0x2a)
26+
#define MP_BC_LOAD_SUBSCR (0x2b)
2627

2728
#define MP_BC_STORE_FAST_0 (0x30)
2829
#define MP_BC_STORE_FAST_1 (0x31)

py/compile.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t
670670
compile_node(comp, pns1->nodes[0]);
671671
if (assign_kind == ASSIGN_AUG_LOAD) {
672672
EMIT(dup_top_two);
673-
EMIT_ARG(binary_op, MP_BINARY_OP_SUBSCR);
673+
EMIT(load_subscr);
674674
} else {
675675
EMIT(store_subscr);
676676
}
@@ -2599,7 +2599,7 @@ void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
25992599
void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
26002600
// object who's index we want is on top of stack
26012601
compile_node(comp, pns->nodes[0]); // the index
2602-
EMIT_ARG(binary_op, MP_BINARY_OP_SUBSCR);
2602+
EMIT(load_subscr);
26032603
}
26042604

26052605
void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {

py/emit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ typedef struct _emit_method_table_t {
5050
void (*load_attr)(emit_t *emit, qstr qstr);
5151
void (*load_method)(emit_t *emit, qstr qstr);
5252
void (*load_build_class)(emit_t *emit);
53+
void (*load_subscr)(emit_t *emit);
5354
void (*store_fast)(emit_t *emit, qstr qstr, int local_num);
5455
void (*store_deref)(emit_t *emit, qstr qstr, int local_num);
5556
void (*store_name)(emit_t *emit, qstr qstr);

py/emitbc.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,11 @@ STATIC void emit_bc_load_build_class(emit_t *emit) {
477477
emit_write_byte_code_byte(emit, MP_BC_LOAD_BUILD_CLASS);
478478
}
479479

480+
STATIC void emit_bc_load_subscr(emit_t *emit) {
481+
emit_bc_pre(emit, -1);
482+
emit_write_byte_code_byte(emit, MP_BC_LOAD_SUBSCR);
483+
}
484+
480485
STATIC void emit_bc_store_fast(emit_t *emit, qstr qstr, int local_num) {
481486
assert(local_num >= 0);
482487
emit_bc_pre(emit, -1);
@@ -873,6 +878,7 @@ const emit_method_table_t emit_bc_method_table = {
873878
emit_bc_load_attr,
874879
emit_bc_load_method,
875880
emit_bc_load_build_class,
881+
emit_bc_load_subscr,
876882
emit_bc_store_fast,
877883
emit_bc_store_deref,
878884
emit_bc_store_name,

py/emitcpy.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,13 @@ STATIC void emit_cpy_load_build_class(emit_t *emit) {
281281
}
282282
}
283283

284+
STATIC void emit_cpy_load_subscr(emit_t *emit) {
285+
emit_pre(emit, -1, 1);
286+
if (emit->pass == PASS_3) {
287+
printf("BINARY_SUBSCR\n");
288+
}
289+
}
290+
284291
STATIC void emit_cpy_store_fast(emit_t *emit, qstr qstr, int local_num) {
285292
emit_pre(emit, -1, 3);
286293
if (emit->pass == PASS_3) {
@@ -555,7 +562,6 @@ STATIC void emit_cpy_binary_op(emit_t *emit, mp_binary_op_t op) {
555562
}
556563
if (emit->pass == PASS_3) {
557564
switch (op) {
558-
case MP_BINARY_OP_SUBSCR: printf("BINARY_SUBSCR\n"); break;
559565
case MP_BINARY_OP_OR: printf("BINARY_OR\n"); break;
560566
case MP_BINARY_OP_XOR: printf("BINARY_XOR\n"); break;
561567
case MP_BINARY_OP_AND: printf("BINARY_AND\n"); break;
@@ -817,6 +823,7 @@ const emit_method_table_t emit_cpython_method_table = {
817823
emit_cpy_load_attr,
818824
emit_cpy_load_method,
819825
emit_cpy_load_build_class,
826+
emit_cpy_load_subscr,
820827
emit_cpy_store_fast,
821828
emit_cpy_store_deref,
822829
emit_cpy_store_name,

py/emitnative.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,18 @@ STATIC void emit_native_load_build_class(emit_t *emit) {
778778
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
779779
}
780780

781+
STATIC void emit_native_load_subscr(emit_t *emit) {
782+
vtype_kind_t vtype_lhs, vtype_rhs;
783+
emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_2, &vtype_lhs, REG_ARG_1);
784+
if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) {
785+
emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, mp_obj_subscr, (machine_uint_t)MP_OBJ_SENTINEL, REG_ARG_3);
786+
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
787+
} else {
788+
printf("ViperTypeError: can't do subscr of types %d and %d\n", vtype_lhs, vtype_rhs);
789+
assert(0);
790+
}
791+
}
792+
781793
STATIC void emit_native_store_fast(emit_t *emit, qstr qstr, int local_num) {
782794
vtype_kind_t vtype;
783795
#if N_X64
@@ -850,7 +862,7 @@ STATIC void emit_native_store_subscr(emit_t *emit) {
850862
assert(vtype_index == VTYPE_PYOBJ);
851863
assert(vtype_base == VTYPE_PYOBJ);
852864
assert(vtype_value == VTYPE_PYOBJ);
853-
emit_call(emit, MP_F_STORE_SUBSCR, mp_store_subscr);
865+
emit_call(emit, MP_F_OBJ_SUBSCR, mp_obj_subscr);
854866
}
855867

856868
STATIC void emit_native_delete_fast(emit_t *emit, qstr qstr, int local_num) {
@@ -882,8 +894,11 @@ STATIC void emit_native_delete_attr(emit_t *emit, qstr qstr) {
882894
}
883895

884896
STATIC void emit_native_delete_subscr(emit_t *emit) {
885-
// not supported
886-
assert(0);
897+
vtype_kind_t vtype_index, vtype_base;
898+
emit_pre_pop_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1); // index, base
899+
assert(vtype_index == VTYPE_PYOBJ);
900+
assert(vtype_base == VTYPE_PYOBJ);
901+
emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, mp_obj_subscr, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3);
887902
}
888903

889904
STATIC void emit_native_dup_top(emit_t *emit) {
@@ -1328,6 +1343,7 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
13281343
emit_native_load_attr,
13291344
emit_native_load_method,
13301345
emit_native_load_build_class,
1346+
emit_native_load_subscr,
13311347
emit_native_store_fast,
13321348
emit_native_store_deref,
13331349
emit_native_store_name,

py/emitpass1.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,5 @@ const emit_method_table_t emit_pass1_method_table = {
190190
(void*)emit_pass1_dummy,
191191
(void*)emit_pass1_dummy,
192192
(void*)emit_pass1_dummy,
193+
(void*)emit_pass1_dummy,
193194
};

py/obj.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,24 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {
332332
}
333333
}
334334

335+
mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) {
336+
mp_obj_type_t *type = mp_obj_get_type(base);
337+
if (type->subscr != NULL) {
338+
mp_obj_t ret = type->subscr(base, index, value);
339+
if (ret != MP_OBJ_NOT_SUPPORTED) {
340+
return ret;
341+
}
342+
// TODO: call base classes here?
343+
}
344+
if (value == MP_OBJ_NULL) {
345+
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item deletion", mp_obj_get_type_str(base)));
346+
} else if (value == MP_OBJ_SENTINEL) {
347+
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not subscriptable", mp_obj_get_type_str(base)));
348+
} else {
349+
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item assignment", mp_obj_get_type_str(base)));
350+
}
351+
}
352+
335353
// Return input argument. Useful as .getiter for objects which are
336354
// their own iterators, etc.
337355
mp_obj_t mp_identity(mp_obj_t self) {

py/obj.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
2828

2929
#define MP_OBJ_SENTINEL ((mp_obj_t)8)
3030

31+
// The NOT_SUPPORTED object is a return value that indicates an unsupported operation.
32+
33+
#define MP_OBJ_NOT_SUPPORTED ((mp_obj_t)16)
34+
3135
// These macros check for small int, qstr or object, and access small int and qstr values
3236
// - xxxx...xxx1: a small int, bits 1 and above are the value
3337
// - xxxx...xx10: a qstr, bits 2 and above are the value
@@ -165,7 +169,7 @@ typedef mp_obj_t (*mp_unary_op_fun_t)(int op, mp_obj_t);
165169
typedef mp_obj_t (*mp_binary_op_fun_t)(int op, mp_obj_t, mp_obj_t);
166170
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
167171
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
168-
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
172+
typedef mp_obj_t (*mp_subscr_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
169173

170174
typedef struct _mp_method_t {
171175
qstr name;
@@ -222,16 +226,13 @@ struct _mp_obj_type_t {
222226
mp_load_attr_fun_t load_attr;
223227
mp_store_attr_fun_t store_attr; // if value is MP_OBJ_NULL, then delete that attribute
224228

225-
// Implements container[index] = val. If val == MP_OBJ_NULL, then it's a delete.
226-
// Note that load_item is implemented by binary_op(RT_BINARY_OP_SUBSCR)
227-
mp_store_item_fun_t store_item;
229+
mp_subscr_fun_t subscr; // implements load, store, delete subscripting
230+
// value=MP_OBJ_NULL means delete, value=MP_OBJ_SENTINEL means load, else store
231+
// can return MP_OBJ_NOT_SUPPORTED
228232

229233
mp_fun_1_t getiter;
230234
mp_fun_1_t iternext; // may return MP_OBJ_NULL as an optimisation instead of raising StopIteration() (with no args)
231235

232-
// Alternatively, pointer(s) to interfaces to save space
233-
// in mp_obj_type_t at the expense of extra pointer and extra dereference
234-
// when actually used.
235236
mp_buffer_p_t buffer_p;
236237
const mp_stream_p_t *stream_p;
237238

@@ -242,8 +243,6 @@ struct _mp_obj_type_t {
242243
/*
243244
What we might need to add here:
244245
245-
store_subscr list dict
246-
247246
len str tuple list map
248247
abs float complex
249248
hash bool int none str
@@ -395,6 +394,7 @@ void mp_obj_get_array(mp_obj_t o, uint *len, mp_obj_t **items);
395394
void mp_obj_get_array_fixed_n(mp_obj_t o, uint len, mp_obj_t **items);
396395
uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index, bool is_slice);
397396
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); /* may return MP_OBJ_NULL */
397+
mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val);
398398

399399
// bool
400400
// TODO make lower case when it has proven itself

py/objarray.c

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -112,21 +112,6 @@ STATIC mp_obj_t array_unary_op(int op, mp_obj_t o_in) {
112112
}
113113
}
114114

115-
STATIC mp_obj_t array_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
116-
mp_obj_array_t *o = lhs;
117-
switch (op) {
118-
case MP_BINARY_OP_SUBSCR:
119-
{
120-
uint index = mp_get_index(o->base.type, o->len, rhs, false);
121-
return mp_binary_get_val_array(o->typecode, o->items, index);
122-
}
123-
124-
default:
125-
// op not supported
126-
return MP_OBJ_NULL;
127-
}
128-
}
129-
130115
STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) {
131116
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_array) || MP_OBJ_IS_TYPE(self_in, &mp_type_bytearray));
132117
mp_obj_array_t *self = self_in;
@@ -142,15 +127,22 @@ STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) {
142127
}
143128
STATIC MP_DEFINE_CONST_FUN_OBJ_2(array_append_obj, array_append);
144129

145-
STATIC bool array_store_item(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
130+
STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
146131
if (value == MP_OBJ_NULL) {
147132
// delete item; does this need to be implemented?
148-
return false;
133+
return MP_OBJ_NOT_SUPPORTED;
134+
} else {
135+
mp_obj_array_t *o = self_in;
136+
uint index = mp_get_index(o->base.type, o->len, index_in, false);
137+
if (value == MP_OBJ_SENTINEL) {
138+
// load
139+
return mp_binary_get_val_array(o->typecode, o->items, index);
140+
} else {
141+
// store
142+
mp_binary_set_val_array(o->typecode, o->items, index, value);
143+
return mp_const_none;
144+
}
149145
}
150-
mp_obj_array_t *o = self_in;
151-
uint index = mp_get_index(o->base.type, o->len, index_in, false);
152-
mp_binary_set_val_array(o->typecode, o->items, index, value);
153-
return true;
154146
}
155147

156148
STATIC machine_int_t array_get_buffer(mp_obj_t o_in, buffer_info_t *bufinfo, int flags) {
@@ -173,8 +165,7 @@ const mp_obj_type_t mp_type_array = {
173165
.make_new = array_make_new,
174166
.getiter = array_iterator_new,
175167
.unary_op = array_unary_op,
176-
.binary_op = array_binary_op,
177-
.store_item = array_store_item,
168+
.subscr = array_subscr,
178169
.buffer_p = { .get_buffer = array_get_buffer },
179170
.locals_dict = (mp_obj_t)&array_locals_dict,
180171
};
@@ -186,8 +177,7 @@ const mp_obj_type_t mp_type_bytearray = {
186177
.make_new = bytearray_make_new,
187178
.getiter = array_iterator_new,
188179
.unary_op = array_unary_op,
189-
.binary_op = array_binary_op,
190-
.store_item = array_store_item,
180+
.subscr = array_subscr,
191181
.buffer_p = { .get_buffer = array_get_buffer },
192182
.locals_dict = (mp_obj_t)&array_locals_dict,
193183
};

0 commit comments

Comments
 (0)