dict views now, refactoring later.

This commit is contained in:
John R. Lenton 2014-01-10 01:00:20 +00:00
parent 2d45429122
commit 9ec3a87189
2 changed files with 139 additions and 0 deletions

View File

@ -246,6 +246,136 @@ static mp_obj_t dict_update(mp_obj_t self_in, mp_obj_t iterable) {
static MP_DEFINE_CONST_FUN_OBJ_2(dict_update_obj, dict_update);
/******************************************************************************/
/* dict views */
static const mp_obj_type_t dict_view_type;
static const mp_obj_type_t dict_view_it_type;
typedef enum _mp_dict_view_kind_t {
MP_DICT_VIEW_ITEMS,
MP_DICT_VIEW_KEYS,
MP_DICT_VIEW_VALUES,
} mp_dict_view_kind_t;
static char *mp_dict_view_names[] = {"dict_items", "dict_keys", "dict_values"};
typedef struct _mp_obj_dict_view_it_t {
mp_obj_base_t base;
mp_dict_view_kind_t kind;
mp_obj_dict_it_t *iter;
machine_uint_t cur;
} mp_obj_dict_view_it_t;
typedef struct _mp_obj_dict_view_t {
mp_obj_base_t base;
mp_obj_dict_t *dict;
mp_dict_view_kind_t kind;
} mp_obj_dict_view_t;
static mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &dict_view_it_type));
mp_obj_dict_view_it_t *self = self_in;
mp_map_elem_t *next = dict_it_iternext_elem(self->iter);
if (next != NULL) {
switch (self->kind) {
case MP_DICT_VIEW_ITEMS:
{
mp_obj_t items[] = {next->key, next->value};
return mp_obj_new_tuple(2, items);
}
case MP_DICT_VIEW_KEYS:
{
return next->key;
}
case MP_DICT_VIEW_VALUES:
{
return next->value;
}
default:
{
assert(0); /* can't happen */
}
}
} else {
return mp_const_stop_iteration;
}
}
static const mp_obj_type_t dict_view_it_type = {
{ &mp_const_type },
"dict_view_iterator",
.iternext = dict_view_it_iternext,
.methods = NULL, /* set operations still to come */
};
static mp_obj_t dict_view_getiter(mp_obj_t view_in) {
assert(MP_OBJ_IS_TYPE(view_in, &dict_view_type));
mp_obj_dict_view_t *view = view_in;
mp_obj_dict_view_it_t *o = m_new_obj(mp_obj_dict_view_it_t);
o->base.type = &dict_view_it_type;
o->kind = view->kind;
o->iter = mp_obj_new_dict_iterator(view->dict, 0);
return o;
}
static void dict_view_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &dict_view_type));
mp_obj_dict_view_t *self = self_in;
bool first = true;
print(env, mp_dict_view_names[self->kind]);
print(env, "([");
mp_obj_t *self_iter = dict_view_getiter(self);
mp_obj_t *next = NULL;
while ((next = dict_view_it_iternext(self_iter)) != mp_const_stop_iteration) {
if (!first) {
print(env, ", ");
}
first = false;
mp_obj_print_helper(print, env, next);
}
print(env, "])");
}
static const mp_obj_type_t dict_view_type = {
{ &mp_const_type },
"dict_view",
.print = dict_view_print,
.getiter = dict_view_getiter,
};
mp_obj_t mp_obj_new_dict_view(mp_obj_dict_t *dict, mp_dict_view_kind_t kind) {
mp_obj_dict_view_t *o = m_new_obj(mp_obj_dict_view_t);
o->base.type = &dict_view_type;
o->dict = dict;
o->kind = kind;
return o;
}
static mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) {
assert(MP_OBJ_IS_TYPE(self_in, &dict_type));
mp_obj_dict_t *self = self_in;
return mp_obj_new_dict_view(self, kind);
}
static mp_obj_t dict_items(mp_obj_t self_in) {
return dict_view(self_in, MP_DICT_VIEW_ITEMS);
}
static MP_DEFINE_CONST_FUN_OBJ_1(dict_items_obj, dict_items);
static mp_obj_t dict_keys(mp_obj_t self_in) {
return dict_view(self_in, MP_DICT_VIEW_KEYS);
}
static MP_DEFINE_CONST_FUN_OBJ_1(dict_keys_obj, dict_keys);
static mp_obj_t dict_values(mp_obj_t self_in) {
return dict_view(self_in, MP_DICT_VIEW_VALUES);
}
static MP_DEFINE_CONST_FUN_OBJ_1(dict_values_obj, dict_values);
/******************************************************************************/
/* dict constructors & etc */
@ -253,10 +383,13 @@ static const mp_method_t dict_type_methods[] = {
{ "clear", &dict_clear_obj },
{ "copy", &dict_copy_obj },
{ "get", &dict_get_obj },
{ "items", &dict_items_obj },
{ "keys", &dict_keys_obj },
{ "pop", &dict_pop_obj },
{ "popitem", &dict_popitem_obj },
{ "setdefault", &dict_setdefault_obj },
{ "update", &dict_update_obj },
{ "values", &dict_values_obj },
{ NULL, NULL }, // end-of-list sentinel
};

View File

@ -0,0 +1,6 @@
d = {1: 2}
for m in d.items, d.values, d.keys:
print(m())
print(list(m()))
# set operations still to come