Beispiel #1
0
STATIC mp_obj_t dict_get_helper(size_t n_args, const mp_obj_t *args, mp_map_lookup_kind_t lookup_kind) {
    mp_check_self(mp_obj_is_dict_type(args[0]));
    mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
    if (lookup_kind != MP_MAP_LOOKUP) {
        mp_ensure_not_fixed(self);
    }
    mp_map_elem_t *elem = mp_map_lookup(&self->map, args[1], lookup_kind);
    mp_obj_t value;
    if (elem == NULL || elem->value == MP_OBJ_NULL) {
        if (n_args == 2) {
            if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
                nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, args[1]));
            } else {
                value = mp_const_none;
            }
        } else {
            value = args[2];
        }
        if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
            elem->value = value;
        }
    } else {
        value = elem->value;
        if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
            elem->value = MP_OBJ_NULL; // so that GC can collect the deleted value
        }
    }
    return value;
}
Beispiel #2
0
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) {
    mp_check_self(mp_obj_is_dict_type(self_in));
    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
    mp_ensure_not_fixed(self);
    mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
    return self_in;
}
Beispiel #3
0
STATIC mp_obj_t dict_clear(mp_obj_t self_in) {
    mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);

    mp_map_clear(&self->map);

    return mp_const_none;
}
Beispiel #4
0
STATIC mp_obj_t dict_clear(mp_obj_t self_in) {
    mp_check_self(mp_obj_is_dict_type(self_in));
    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
    mp_ensure_not_fixed(self);

    mp_map_clear(&self->map);

    return mp_const_none;
}
Beispiel #5
0
STATIC mp_obj_t dict_setdefault(size_t n_args, const mp_obj_t *args) {
    mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0]));
    mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);

    return dict_get_helper(&self->map,
                           args[1],
                           n_args == 3 ? args[2] : MP_OBJ_NULL,
                           MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
}
Beispiel #6
0
// Don't pass MP_BINARY_OP_NOT_EQUAL here
STATIC bool list_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) {
    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
    if (!MP_OBJ_IS_TYPE(another_in, &mp_type_list)) {
        return false;
    }
    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
    mp_obj_list_t *another = MP_OBJ_TO_PTR(another_in);

    return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len);
}
Beispiel #7
0
STATIC mp_obj_t dict_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
    assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t));
    mp_check_self(mp_obj_is_dict_type(self_in));
    mp_obj_dict_view_it_t *o = (mp_obj_dict_view_it_t*)iter_buf;
    o->base.type = &dict_view_it_type;
    o->kind = MP_DICT_VIEW_KEYS;
    o->dict = self_in;
    o->cur = 0;
    return MP_OBJ_FROM_PTR(o);
}
Beispiel #8
0
STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in) {
    mp_check_self(MP_OBJ_IS_TYPE(view_in, &dict_view_type));
    mp_obj_dict_view_t *view = MP_OBJ_TO_PTR(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->dict = view->dict;
    o->cur = 0;
    return MP_OBJ_FROM_PTR(o);
}
Beispiel #9
0
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
    if (self->len >= self->alloc) {
        self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc * 2);
        self->alloc *= 2;
        mp_seq_clear(self->items, self->len + 1, self->alloc, sizeof(*self->items));
    }
    self->items[self->len++] = arg;
    return mp_const_none; // return None, as per CPython
}
Beispiel #10
0
STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in, mp_obj_iter_buf_t *iter_buf) {
    assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t));
    mp_check_self(mp_obj_is_type(view_in, &dict_view_type));
    mp_obj_dict_view_t *view = MP_OBJ_TO_PTR(view_in);
    mp_obj_dict_view_it_t *o = (mp_obj_dict_view_it_t*)iter_buf;
    o->base.type = &dict_view_it_type;
    o->kind = view->kind;
    o->dict = view->dict;
    o->cur = 0;
    return MP_OBJ_FROM_PTR(o);
}
Beispiel #11
0
STATIC mp_obj_t dict_copy(mp_obj_t self_in) {
    mp_check_self(mp_obj_is_dict_type(self_in));
    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
    mp_obj_t other_out = mp_obj_new_dict(self->map.alloc);
    mp_obj_dict_t *other = MP_OBJ_TO_PTR(other_out);
    other->base.type = self->base.type;
    other->map.used = self->map.used;
    other->map.all_keys_are_qstrs = self->map.all_keys_are_qstrs;
    other->map.is_fixed = 0;
    other->map.is_ordered = self->map.is_ordered;
    memcpy(other->map.table, self->map.table, self->map.alloc * sizeof(mp_map_elem_t));
    return other_out;
}
Beispiel #12
0
STATIC mp_obj_t reversed_iternext(mp_obj_t self_in) {
    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_reversed));
    mp_obj_reversed_t *self = MP_OBJ_TO_PTR(self_in);

    // "raise" stop iteration if we are at the end (the start) of the sequence
    if (self->cur_index == 0) {
        return MP_OBJ_STOP_ITERATION;
    }

    // pre-decrement and index sequence
    self->cur_index -= 1;
    return mp_obj_subscr(self->seq, MP_OBJ_NEW_SMALL_INT(self->cur_index), MP_OBJ_SENTINEL);
}
Beispiel #13
0
mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {
    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance));
    mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in);
    if (self->code_state.ip == 0) {
        // Trying to resume already stopped generator
        *ret_val = MP_OBJ_STOP_ITERATION;
        return MP_VM_RETURN_NORMAL;
    }
    if (self->code_state.sp == self->code_state.state - 1) {
        if (send_value != mp_const_none) {
            mp_raise_TypeError("can't send non-None value to a just-started generator");
        }
    } else {
        *self->code_state.sp = send_value;
    }
    mp_obj_dict_t *old_globals = mp_globals_get();
    mp_globals_set(self->globals);
    mp_vm_return_kind_t ret_kind = mp_execute_bytecode(&self->code_state, throw_value);
    mp_globals_set(old_globals);

    switch (ret_kind) {
        case MP_VM_RETURN_NORMAL:
        default:
            // Explicitly mark generator as completed. If we don't do this,
            // subsequent next() may re-execute statements after last yield
            // again and again, leading to side effects.
            // TODO: check how return with value behaves under such conditions
            // in CPython.
            self->code_state.ip = 0;
            *ret_val = *self->code_state.sp;
            break;

        case MP_VM_RETURN_YIELD:
            *ret_val = *self->code_state.sp;
            if (*ret_val == MP_OBJ_STOP_ITERATION) {
                self->code_state.ip = 0;
            }
            break;

        case MP_VM_RETURN_EXCEPTION: {
            size_t n_state = mp_decode_uint_value(self->code_state.fun_bc->bytecode);
            self->code_state.ip = 0;
            *ret_val = self->code_state.state[n_state - 1];
            break;
        }
    }

    return ret_kind;
}
Beispiel #14
0
STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
    mp_check_self(mp_obj_is_dict_type(args[0]));
    mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
    mp_ensure_not_fixed(self);

    mp_arg_check_num(n_args, kwargs->used, 1, 2, true);

    if (n_args == 2) {
        // given a positional argument

        if (mp_obj_is_dict_type(args[1])) {
            // update from other dictionary (make sure other is not self)
            if (args[1] != args[0]) {
                size_t cur = 0;
                mp_map_elem_t *elem = NULL;
                while ((elem = dict_iter_next((mp_obj_dict_t*)MP_OBJ_TO_PTR(args[1]), &cur)) != NULL) {
                    mp_map_lookup(&self->map, elem->key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = elem->value;
                }
            }
        } else {
            // update from a generic iterable of pairs
            mp_obj_t iter = mp_getiter(args[1], NULL);
            mp_obj_t next = MP_OBJ_NULL;
            while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
                mp_obj_t inneriter = mp_getiter(next, NULL);
                mp_obj_t key = mp_iternext(inneriter);
                mp_obj_t value = mp_iternext(inneriter);
                mp_obj_t stop = mp_iternext(inneriter);
                if (key == MP_OBJ_STOP_ITERATION
                    || value == MP_OBJ_STOP_ITERATION
                    || stop != MP_OBJ_STOP_ITERATION) {
                    mp_raise_ValueError("dict update sequence has wrong length");
                } else {
                    mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
                }
            }
        }
    }

    // update the dict with any keyword args
    for (size_t i = 0; i < kwargs->alloc; i++) {
        if (mp_map_slot_is_filled(kwargs, i)) {
            mp_map_lookup(&self->map, kwargs->table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = kwargs->table[i].value;
        }
    }

    return mp_const_none;
}
Beispiel #15
0
// Don't pass MP_BINARY_OP_NOT_EQUAL here
STATIC bool tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) {
    // type check is done on getiter method to allow tuple, namedtuple, attrtuple
    mp_check_self(mp_obj_get_type(self_in)->getiter == mp_obj_tuple_getiter);
    mp_obj_type_t *another_type = mp_obj_get_type(another_in);
    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
    if (another_type->getiter != mp_obj_tuple_getiter) {
        // Slow path for user subclasses
        another_in = mp_instance_cast_to_native_base(another_in, MP_OBJ_FROM_PTR(&mp_type_tuple));
        if (another_in == MP_OBJ_NULL) {
            return false;
        }
    }
    mp_obj_tuple_t *another = MP_OBJ_TO_PTR(another_in);

    return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len);
}
Beispiel #16
0
STATIC mp_obj_t dict_popitem(mp_obj_t self_in) {
    mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
    size_t cur = 0;
    mp_map_elem_t *next = dict_iter_next(self, &cur);
    if (next == NULL) {
        mp_raise_msg(&mp_type_KeyError, "popitem(): dictionary is empty");
    }
    self->map.used--;
    mp_obj_t items[] = {next->key, next->value};
    next->key = MP_OBJ_SENTINEL; // must mark key as sentinel to indicate that it was deleted
    next->value = MP_OBJ_NULL;
    mp_obj_t tuple = mp_obj_new_tuple(2, items);

    return tuple;
}
Beispiel #17
0
STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
    (void)kind;
    mp_check_self(MP_OBJ_IS_TYPE(self_in, &dict_view_type));
    mp_obj_dict_view_t *self = MP_OBJ_TO_PTR(self_in);
    bool first = true;
    mp_print_str(print, mp_dict_view_names[self->kind]);
    mp_print_str(print, "([");
    mp_obj_t self_iter = dict_view_getiter(self_in);
    mp_obj_t next = MP_OBJ_NULL;
    while ((next = dict_view_it_iternext(self_iter)) != MP_OBJ_STOP_ITERATION) {
        if (!first) {
            mp_print_str(print, ", ");
        }
        first = false;
        mp_obj_print_helper(print, next, PRINT_REPR);
    }
    mp_print_str(print, "])");
}
STATIC mp_obj_t zip_iternext(mp_obj_t self_in) {
    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_zip));
    mp_obj_zip_t *self = MP_OBJ_TO_PTR(self_in);
    if (self->n_iters == 0) {
        return MP_OBJ_STOP_ITERATION;
    }
    mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(self->n_iters, NULL));

    for (mp_uint_t i = 0; i < self->n_iters; i++) {
        mp_obj_t next = mp_iternext(self->iters[i]);
        if (next == MP_OBJ_STOP_ITERATION) {
            mp_obj_tuple_del(MP_OBJ_FROM_PTR(tuple));
            return MP_OBJ_STOP_ITERATION;
        }
        tuple->items[i] = next;
    }
    return MP_OBJ_FROM_PTR(tuple);
}
Beispiel #19
0
STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) {
    mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_list));
    mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]);
    if (self->len == 0) {
        mp_raise_msg(&mp_type_IndexError, "pop from empty list");
    }
    size_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false);
    mp_obj_t ret = self->items[index];
    self->len -= 1;
    memmove(self->items + index, self->items + index + 1, (self->len - index) * sizeof(mp_obj_t));
    // Clear stale pointer from slot which just got freed to prevent GC issues
    self->items[self->len] = MP_OBJ_NULL;
    if (self->alloc > LIST_MIN_ALLOC && self->alloc > 2 * self->len) {
        self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc/2);
        self->alloc /= 2;
    }
    return ret;
}
Beispiel #20
0
STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) {
    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
    if (MP_OBJ_IS_TYPE(arg_in, &mp_type_list)) {
        mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
        mp_obj_list_t *arg = MP_OBJ_TO_PTR(arg_in);

        if (self->len + arg->len > self->alloc) {
            // TODO: use alloc policy for "4"
            self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4);
            self->alloc = self->len + arg->len + 4;
            mp_seq_clear(self->items, self->len + arg->len, self->alloc, sizeof(*self->items));
        }

        memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len);
        self->len += arg->len;
    } else {
        list_extend_from_iter(self_in, arg_in);
    }
    return mp_const_none; // return None, as per CPython
}
Beispiel #21
0
STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
    mp_check_self(mp_obj_is_type(self_in, &dict_view_it_type));
    mp_obj_dict_view_it_t *self = MP_OBJ_TO_PTR(self_in);
    mp_map_elem_t *next = dict_iter_next(MP_OBJ_TO_PTR(self->dict), &self->cur);

    if (next == NULL) {
        return MP_OBJ_STOP_ITERATION;
    } else {
        switch (self->kind) {
            case MP_DICT_VIEW_ITEMS:
            default: {
                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;
        }
    }
}
Beispiel #22
0
STATIC mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) {
    mp_check_self(mp_obj_is_dict_type(self_in));
    return mp_obj_new_dict_view(self_in, kind);
}
Beispiel #23
0
void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) {
    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
    mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
}
Beispiel #24
0
mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {
    MP_STACK_CHECK();
    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance));
    mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in);
    if (self->code_state.ip == 0) {
        // Trying to resume already stopped generator
        *ret_val = MP_OBJ_STOP_ITERATION;
        return MP_VM_RETURN_NORMAL;
    }
    if (self->code_state.sp == self->code_state.state - 1) {
        if (send_value != mp_const_none) {
            mp_raise_TypeError("can't send non-None value to a just-started generator");
        }
    } else {
        #if MICROPY_PY_GENERATOR_PEND_THROW
        // If exception is pending (set using .pend_throw()), process it now.
        if (*self->code_state.sp != mp_const_none) {
            throw_value = *self->code_state.sp;
            *self->code_state.sp = MP_OBJ_NULL;
        } else
        #endif
        {
            *self->code_state.sp = send_value;
        }
    }

    // We set self->globals=NULL while executing, for a sentinel to ensure the generator
    // cannot be reentered during execution
    if (self->globals == NULL) {
        mp_raise_ValueError("generator already executing");
    }

    // Set up the correct globals context for the generator and execute it
    self->code_state.old_globals = mp_globals_get();
    mp_globals_set(self->globals);
    self->globals = NULL;
    mp_vm_return_kind_t ret_kind = mp_execute_bytecode(&self->code_state, throw_value);
    self->globals = mp_globals_get();
    mp_globals_set(self->code_state.old_globals);

    switch (ret_kind) {
        case MP_VM_RETURN_NORMAL:
        default:
            // Explicitly mark generator as completed. If we don't do this,
            // subsequent next() may re-execute statements after last yield
            // again and again, leading to side effects.
            // TODO: check how return with value behaves under such conditions
            // in CPython.
            self->code_state.ip = 0;
            *ret_val = *self->code_state.sp;
            break;

        case MP_VM_RETURN_YIELD:
            *ret_val = *self->code_state.sp;
            #if MICROPY_PY_GENERATOR_PEND_THROW
            *self->code_state.sp = mp_const_none;
            #endif
            break;

        case MP_VM_RETURN_EXCEPTION: {
            size_t n_state = mp_decode_uint_value(self->code_state.fun_bc->bytecode);
            self->code_state.ip = 0;
            *ret_val = self->code_state.state[n_state - 1];
            break;
        }
    }

    return ret_kind;
}
Beispiel #25
0
STATIC mp_obj_t tuple_index(size_t n_args, const mp_obj_t *args) {
    mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_tuple));
    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(args[0]);
    return mp_seq_index_obj(self->items, self->len, n_args, args);
}
Beispiel #26
0
mp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key) {
    mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
    dict_get_helper(&self->map, key, MP_OBJ_NULL, MP_MAP_LOOKUP_REMOVE_IF_FOUND);
    return self_in;
}
Beispiel #27
0
mp_map_t *mp_obj_dict_get_map(mp_obj_t self_in) {
    mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
    return &self->map;
}
Beispiel #28
0
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) {
    mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
    mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
    return self_in;
}
Beispiel #29
0
STATIC mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) {
    mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
    return mp_obj_new_dict_view(self_in, kind);
}
Beispiel #30
0
STATIC mp_obj_t tuple_count(mp_obj_t self_in, mp_obj_t value) {
    mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));
    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
    return mp_seq_count_obj(self->items, self->len, value);
}