summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/builtin.c21
-rw-r--r--py/obj.c24
-rw-r--r--py/obj.h1
-rw-r--r--py/objdict.c57
-rw-r--r--py/objlist.c15
-rw-r--r--tests/basics/tests/dict_fromkeys.py10
-rw-r--r--tests/basics/tests/list_mult.py4
7 files changed, 114 insertions, 18 deletions
diff --git a/py/builtin.c b/py/builtin.c
index 50e9c02df5..078f4b49c3 100644
--- a/py/builtin.c
+++ b/py/builtin.c
@@ -166,25 +166,12 @@ static mp_obj_t mp_builtin_iter(mp_obj_t o_in) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter);
mp_obj_t mp_builtin_len(mp_obj_t o_in) {
- mp_small_int_t len = 0;
- if (MP_OBJ_IS_TYPE(o_in, &str_type)) {
- len = strlen(qstr_str(mp_obj_str_get(o_in)));
- } else if (MP_OBJ_IS_TYPE(o_in, &tuple_type)) {
- uint seq_len;
- mp_obj_t *seq_items;
- mp_obj_tuple_get(o_in, &seq_len, &seq_items);
- len = seq_len;
- } else if (MP_OBJ_IS_TYPE(o_in, &list_type)) {
- uint seq_len;
- mp_obj_t *seq_items;
- mp_obj_list_get(o_in, &seq_len, &seq_items);
- len = seq_len;
- } else if (MP_OBJ_IS_TYPE(o_in, &dict_type)) {
- len = mp_obj_dict_len(o_in);
- } else {
+ mp_obj_t len = mp_obj_len_maybe(o_in);
+ if (len == NULL) {
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in)));
+ } else {
+ return len;
}
- return MP_OBJ_NEW_SMALL_INT(len);
}
mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args) {
diff --git a/py/obj.c b/py/obj.c
index 7905f05486..dfb450fb8d 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
+#include <string.h>
#include <assert.h>
#include "nlr.h"
@@ -229,3 +230,26 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index)
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "%s indices must be integers, not %s", type->name, mp_obj_get_type_str(index)));
}
}
+
+// may return NULL
+mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {
+ mp_small_int_t len = 0;
+ if (MP_OBJ_IS_TYPE(o_in, &str_type)) {
+ len = strlen(qstr_str(mp_obj_str_get(o_in)));
+ } else if (MP_OBJ_IS_TYPE(o_in, &tuple_type)) {
+ uint seq_len;
+ mp_obj_t *seq_items;
+ mp_obj_tuple_get(o_in, &seq_len, &seq_items);
+ len = seq_len;
+ } else if (MP_OBJ_IS_TYPE(o_in, &list_type)) {
+ uint seq_len;
+ mp_obj_t *seq_items;
+ mp_obj_list_get(o_in, &seq_len, &seq_items);
+ len = seq_len;
+ } else if (MP_OBJ_IS_TYPE(o_in, &dict_type)) {
+ len = mp_obj_dict_len(o_in);
+ } else {
+ return NULL;
+ }
+ return MP_OBJ_NEW_SMALL_INT(len);
+}
diff --git a/py/obj.h b/py/obj.h
index 48080a0ec0..d897d906d9 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -234,6 +234,7 @@ void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
qstr mp_obj_get_qstr(mp_obj_t arg);
mp_obj_t *mp_obj_get_array_fixed_n(mp_obj_t o, machine_int_t n);
uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index);
+mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); /* may return NULL */
// none
extern const mp_obj_type_t none_type;
diff --git a/py/objdict.c b/py/objdict.c
index 6acee3fa78..8902e1020c 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -376,6 +376,61 @@ static mp_obj_t dict_values(mp_obj_t self_in) {
}
static MP_DEFINE_CONST_FUN_OBJ_1(dict_values_obj, dict_values);
+
+/******************************************************************************/
+/* dict metaclass */
+
+static mp_obj_t dict_fromkeys(int n_args, const mp_obj_t *args) {
+ assert(2 <= n_args && n_args <= 3);
+ mp_obj_t iter = rt_getiter(args[1]);
+ mp_obj_t len = mp_obj_len_maybe(iter);
+ mp_obj_t value = mp_const_none;
+ mp_obj_t next = NULL;
+ mp_obj_dict_t *self = NULL;
+
+ if (n_args > 2) {
+ value = args[2];
+ }
+
+ if (len == NULL) {
+ /* object's type doesn't have a __len__ slot */
+ self = mp_obj_new_dict(0);
+ } else {
+ self = mp_obj_new_dict(MP_OBJ_SMALL_INT_VALUE(len));
+ }
+
+ while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
+ mp_map_lookup(&self->map, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
+ }
+
+ return self;
+}
+static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_fromkeys_obj, 2, 3, dict_fromkeys);
+
+static const mp_method_t dict_class_methods[] = {
+ { "fromkeys", &dict_fromkeys_obj },
+ { NULL, NULL }, // end-of-list sentinel
+};
+
+/* this should be unnecessary when inheritance works */
+static void dict_class_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
+ print(env, "<class 'dict'>");
+}
+
+/* this should be unnecessary when inheritance works */
+static mp_obj_t dict_class_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
+ return rt_build_map(0);
+}
+
+static const mp_obj_type_t dict_class = {
+ { &mp_const_type },
+ "dict_class",
+ .print = dict_class_print,
+ .methods = dict_class_methods,
+ .call_n = dict_class_call_n,
+};
+
+
/******************************************************************************/
/* dict constructors & etc */
@@ -394,7 +449,7 @@ static const mp_method_t dict_type_methods[] = {
};
const mp_obj_type_t dict_type = {
- { &mp_const_type },
+ { &dict_class },
"dict",
.print = dict_print,
.make_new = dict_make_new,
diff --git a/py/objlist.c b/py/objlist.c
index 9d8caee339..ce55aa5100 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -81,6 +81,21 @@ static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
memcpy(s->items + o->len, p->items, sizeof(mp_obj_t) * p->len);
return s;
}
+ case RT_BINARY_OP_MULTIPLY:
+ {
+ if (!MP_OBJ_IS_SMALL_INT(rhs)) {
+ return NULL;
+ }
+ int n = MP_OBJ_SMALL_INT_VALUE(rhs);
+ int len = o->len;
+ mp_obj_list_t *s = list_new(len * n);
+ mp_obj_t *dest = s->items;
+ for (int i = 0; i < n; i++) {
+ memcpy(dest, o->items, sizeof(mp_obj_t) * len);
+ dest += len;
+ }
+ return s;
+ }
default:
// op not supported
return NULL;
diff --git a/tests/basics/tests/dict_fromkeys.py b/tests/basics/tests/dict_fromkeys.py
new file mode 100644
index 0000000000..d03f6ae9d2
--- /dev/null
+++ b/tests/basics/tests/dict_fromkeys.py
@@ -0,0 +1,10 @@
+d = dict.fromkeys([1, 2, 3, 4])
+l = list(d.keys())
+l.sort()
+print(l)
+
+d = dict.fromkeys([1, 2, 3, 4], 42)
+l = list(d.values())
+l.sort()
+print(l)
+
diff --git a/tests/basics/tests/list_mult.py b/tests/basics/tests/list_mult.py
new file mode 100644
index 0000000000..ec65fbb3f4
--- /dev/null
+++ b/tests/basics/tests/list_mult.py
@@ -0,0 +1,4 @@
+print([0] * 5)
+a = [1, 2, 3]
+c = a * 3
+print(c)