summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-02-10 21:41:14 +0000
committerDamien George <damien.p.george@gmail.com>2014-02-10 21:41:14 +0000
commit8c2b333affea7445c457c5247df047947bed9b53 (patch)
treeb697957a499162ccca3219dca426b1bcd35cd0c7 /py
parent7d0bfbedd218fadd91e2bbeb6486371ffeb7b682 (diff)
parent2e24ee8d80de20e879275c087ecc1ca9b4d27297 (diff)
downloadmicropython-8c2b333affea7445c457c5247df047947bed9b53.tar.gz
micropython-8c2b333affea7445c457c5247df047947bed9b53.zip
Merge branch 'master' of github.com:micropython/micropython
Diffstat (limited to 'py')
-rw-r--r--py/obj.c1
-rw-r--r--py/obj.h7
-rw-r--r--py/objlist.c76
-rw-r--r--py/objtuple.c62
-rw-r--r--py/qstrdefs.h1
-rw-r--r--py/runtime.c1
-rw-r--r--py/sequence.c85
7 files changed, 160 insertions, 73 deletions
diff --git a/py/obj.c b/py/obj.c
index e21596fdf5..e3e9dbfd55 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -253,3 +253,4 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {
mp_obj_t mp_identity(mp_obj_t self) {
return self;
}
+MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity);
diff --git a/py/obj.h b/py/obj.h
index f99bcc40e7..48d332e200 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -370,6 +370,7 @@ extern const mp_obj_type_t fun_bc_type;
void mp_obj_fun_bc_get(mp_obj_t self_in, int *n_args, uint *n_state, const byte **code);
mp_obj_t mp_identity(mp_obj_t self);
+MP_DECLARE_CONST_FUN_OBJ(mp_identity_obj);
// super
extern const mp_obj_type_t super_type;
@@ -397,5 +398,9 @@ typedef struct _mp_obj_static_class_method_t {
// sequence helpers
void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest);
bool m_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, machine_uint_t *begin, machine_uint_t *end);
-#define m_seq_copy(dest, src, len, item_sz) memcpy(dest, src, len * sizeof(item_sz))
+#define m_seq_copy(dest, src, len, item_t) memcpy(dest, src, len * sizeof(item_t))
+#define m_seq_cat(dest, src1, len1, src2, len2, item_t) { memcpy(dest, src1, len1 * sizeof(item_t)); memcpy(dest + len1, src2, len2 * sizeof(item_t)); }
bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, uint len2);
+bool mp_seq_cmp_objs(int op, const mp_obj_t *items1, uint len1, const mp_obj_t *items2, uint len2);
+mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp_obj_t *args);
+mp_obj_t mp_seq_count_obj(const mp_obj_t *items, uint len, mp_obj_t value);
diff --git a/py/objlist.c b/py/objlist.c
index 14f3a5760a..35bab2a398 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -75,51 +75,8 @@ static bool list_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) {
}
mp_obj_list_t *self = self_in;
mp_obj_list_t *another = another_in;
- if (op == RT_BINARY_OP_EQUAL && self->len != another->len) {
- return false;
- }
-
- // Let's deal only with > & >=
- if (op == RT_BINARY_OP_LESS || op == RT_BINARY_OP_LESS_EQUAL) {
- mp_obj_t t = self;
- self = another;
- another = t;
- if (op == RT_BINARY_OP_LESS) {
- op = RT_BINARY_OP_MORE;
- } else {
- op = RT_BINARY_OP_MORE_EQUAL;
- }
- }
-
- int len = self->len < another->len ? self->len : another->len;
- bool eq_status = true; // empty lists are equal
- bool rel_status;
- for (int i = 0; i < len; i++) {
- eq_status = mp_obj_equal(self->items[i], another->items[i]);
- if (op == RT_BINARY_OP_EQUAL && !eq_status) {
- return false;
- }
- rel_status = (rt_binary_op(op, self->items[i], another->items[i]) == mp_const_true);
- if (!eq_status && !rel_status) {
- return false;
- }
- }
-
- // If we had tie in the last element...
- if (eq_status) {
- // ... and we have lists of different lengths...
- if (self->len != another->len) {
- if (self->len < another->len) {
- // ... then longer list length wins (we deal only with >)
- return false;
- }
- } else if (op == RT_BINARY_OP_MORE) {
- // Otherwise, if we have strict relation, equality means failure
- return false;
- }
- }
- return true;
+ return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len);
}
static mp_obj_t list_unary_op(int op, mp_obj_t self_in) {
@@ -157,8 +114,7 @@ static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
}
mp_obj_list_t *p = rhs;
mp_obj_list_t *s = list_new(o->len + p->len);
- memcpy(s->items, o->items, sizeof(mp_obj_t) * o->len);
- memcpy(s->items + o->len, p->items, sizeof(mp_obj_t) * p->len);
+ m_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t);
return s;
}
case RT_BINARY_OP_INPLACE_ADD:
@@ -304,38 +260,14 @@ static mp_obj_t list_copy(mp_obj_t self_in) {
static mp_obj_t list_count(mp_obj_t self_in, mp_obj_t value) {
assert(MP_OBJ_IS_TYPE(self_in, &list_type));
mp_obj_list_t *self = self_in;
- int count = 0;
- for (int i = 0; i < self->len; i++) {
- if (mp_obj_equal(self->items[i], value)) {
- count++;
- }
- }
-
- return mp_obj_new_int(count);
+ return mp_seq_count_obj(self->items, self->len, value);
}
static mp_obj_t list_index(uint n_args, const mp_obj_t *args) {
assert(2 <= n_args && n_args <= 4);
assert(MP_OBJ_IS_TYPE(args[0], &list_type));
mp_obj_list_t *self = args[0];
- mp_obj_t *value = args[1];
- uint start = 0;
- uint stop = self->len;
-
- if (n_args >= 3) {
- start = mp_get_index(self->base.type, self->len, args[2]);
- if (n_args >= 4) {
- stop = mp_get_index(self->base.type, self->len, args[3]);
- }
- }
-
- for (uint i = start; i < stop; i++) {
- if (mp_obj_equal(self->items[i], value)) {
- return mp_obj_new_int(i);
- }
- }
-
- nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "object not in list"));
+ return mp_seq_index_obj(self->items, self->len, n_args, args);
}
static mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) {
diff --git a/py/objtuple.c b/py/objtuple.c
index 3e5041c9dd..7221db7746 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -74,6 +74,18 @@ static mp_obj_t tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m
}
}
+// Don't pass RT_BINARY_OP_NOT_EQUAL here
+static bool tuple_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) {
+ assert(MP_OBJ_IS_TYPE(self_in, &tuple_type));
+ if (!MP_OBJ_IS_TYPE(another_in, &tuple_type)) {
+ return false;
+ }
+ mp_obj_tuple_t *self = self_in;
+ mp_obj_tuple_t *another = another_in;
+
+ return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len);
+}
+
static mp_obj_t tuple_unary_op(int op, mp_obj_t self_in) {
mp_obj_tuple_t *self = self_in;
switch (op) {
@@ -102,6 +114,35 @@ static mp_obj_t tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
uint index = mp_get_index(o->base.type, o->len, rhs);
return o->items[index];
}
+ case RT_BINARY_OP_ADD:
+ {
+ if (!MP_OBJ_IS_TYPE(rhs, &tuple_type)) {
+ return NULL;
+ }
+ mp_obj_tuple_t *p = rhs;
+ mp_obj_tuple_t *s = mp_obj_new_tuple(o->len + p->len, NULL);
+ m_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t);
+ return s;
+ }
+ case RT_BINARY_OP_MULTIPLY:
+ {
+ if (!MP_OBJ_IS_SMALL_INT(rhs)) {
+ return NULL;
+ }
+ int n = MP_OBJ_SMALL_INT_VALUE(rhs);
+ mp_obj_tuple_t *s = mp_obj_new_tuple(o->len * n, NULL);
+ mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items);
+ return s;
+ }
+ case RT_BINARY_OP_EQUAL:
+ case RT_BINARY_OP_LESS:
+ case RT_BINARY_OP_LESS_EQUAL:
+ case RT_BINARY_OP_MORE:
+ case RT_BINARY_OP_MORE_EQUAL:
+ return MP_BOOL(tuple_cmp_helper(op, lhs, rhs));
+ case RT_BINARY_OP_NOT_EQUAL:
+ return MP_BOOL(!tuple_cmp_helper(RT_BINARY_OP_EQUAL, lhs, rhs));
+
default:
// op not supported
return NULL;
@@ -112,6 +153,26 @@ static mp_obj_t tuple_getiter(mp_obj_t o_in) {
return mp_obj_new_tuple_iterator(o_in, 0);
}
+static mp_obj_t tuple_count(mp_obj_t self_in, mp_obj_t value) {
+ assert(MP_OBJ_IS_TYPE(self_in, &tuple_type));
+ mp_obj_tuple_t *self = self_in;
+ return mp_seq_count_obj(self->items, self->len, value);
+}
+static MP_DEFINE_CONST_FUN_OBJ_2(tuple_count_obj, tuple_count);
+
+static mp_obj_t tuple_index(uint n_args, const mp_obj_t *args) {
+ assert(MP_OBJ_IS_TYPE(args[0], &tuple_type));
+ mp_obj_tuple_t *self = args[0];
+ return mp_seq_index_obj(self->items, self->len, n_args, args);
+}
+static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(tuple_index_obj, 2, 4, tuple_index);
+
+static const mp_method_t tuple_type_methods[] = {
+ { "count", &tuple_count_obj },
+ { "index", &tuple_index_obj },
+ { NULL, NULL }, // end-of-list sentinel
+};
+
const mp_obj_type_t tuple_type = {
{ &mp_const_type },
"tuple",
@@ -120,6 +181,7 @@ const mp_obj_type_t tuple_type = {
.unary_op = tuple_unary_op,
.binary_op = tuple_binary_op,
.getiter = tuple_getiter,
+ .methods = tuple_type_methods,
};
// the zero-length tuple
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index 3d4f4e2488..680c4bcf73 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -37,6 +37,7 @@ Q(IndentationError)
Q(IndexError)
Q(KeyError)
Q(NameError)
+Q(NotImplementedError)
Q(OSError)
Q(SyntaxError)
Q(TypeError)
diff --git a/py/runtime.c b/py/runtime.c
index 0ac470fbc2..aaac884d65 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -177,6 +177,7 @@ void rt_init(void) {
mp_map_add_qstr(&map_builtins, MP_QSTR_OverflowError, mp_obj_new_exception(MP_QSTR_OverflowError));
mp_map_add_qstr(&map_builtins, MP_QSTR_OSError, mp_obj_new_exception(MP_QSTR_OSError));
mp_map_add_qstr(&map_builtins, MP_QSTR_AssertionError, mp_obj_new_exception(MP_QSTR_AssertionError));
+ mp_map_add_qstr(&map_builtins, MP_QSTR_NotImplementedError, mp_obj_new_exception(MP_QSTR_NotImplementedError));
mp_map_add_qstr(&map_builtins, MP_QSTR_StopIteration, mp_obj_new_exception(MP_QSTR_StopIteration));
// built-in objects
diff --git a/py/sequence.c b/py/sequence.c
index 74b4fcfdf8..d8cfd9f3e9 100644
--- a/py/sequence.c
+++ b/py/sequence.c
@@ -91,3 +91,88 @@ bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, u
}
return true;
}
+
+// Special-case comparison function for sequences of mp_obj_t
+// Don't pass RT_BINARY_OP_NOT_EQUAL here
+bool mp_seq_cmp_objs(int op, const mp_obj_t *items1, uint len1, const mp_obj_t *items2, uint len2) {
+ if (op == RT_BINARY_OP_EQUAL && len1 != len2) {
+ return false;
+ }
+
+ // Let's deal only with > & >=
+ if (op == RT_BINARY_OP_LESS || op == RT_BINARY_OP_LESS_EQUAL) {
+ SWAP(const mp_obj_t *, items1, items2);
+ SWAP(uint, len1, len2);
+ if (op == RT_BINARY_OP_LESS) {
+ op = RT_BINARY_OP_MORE;
+ } else {
+ op = RT_BINARY_OP_MORE_EQUAL;
+ }
+ }
+
+ int len = len1 < len2 ? len1 : len2;
+ bool eq_status = true; // empty lists are equal
+ bool rel_status;
+ for (int i = 0; i < len; i++) {
+ eq_status = mp_obj_equal(items1[i], items2[i]);
+ if (op == RT_BINARY_OP_EQUAL && !eq_status) {
+ return false;
+ }
+ rel_status = (rt_binary_op(op, items1[i], items2[i]) == mp_const_true);
+ if (!eq_status && !rel_status) {
+ return false;
+ }
+ }
+
+ // If we had tie in the last element...
+ if (eq_status) {
+ // ... and we have lists of different lengths...
+ if (len1 != len2) {
+ if (len1 < len2) {
+ // ... then longer list length wins (we deal only with >)
+ return false;
+ }
+ } else if (op == RT_BINARY_OP_MORE) {
+ // Otherwise, if we have strict relation, equality means failure
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Special-case of index() which searches for mp_obj_t
+mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp_obj_t *args) {
+ mp_obj_type_t *type = mp_obj_get_type(args[0]);
+ mp_obj_t *value = args[1];
+ uint start = 0;
+ uint stop = len;
+
+ if (n_args >= 3) {
+ start = mp_get_index(type, len, args[2]);
+ if (n_args >= 4) {
+ stop = mp_get_index(type, len, args[3]);
+ }
+ }
+
+ for (uint i = start; i < stop; i++) {
+ if (mp_obj_equal(items[i], value)) {
+ // Common sense says this cannot overflow small int
+ return MP_OBJ_NEW_SMALL_INT(i);
+ }
+ }
+
+ nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "object not in sequence"));
+}
+
+mp_obj_t mp_seq_count_obj(const mp_obj_t *items, uint len, mp_obj_t value) {
+ uint count = 0;
+ for (uint i = 0; i < len; i++) {
+ if (mp_obj_equal(items[i], value)) {
+ count++;
+ }
+ }
+
+ // Common sense says this cannot overflow small int
+ return MP_OBJ_NEW_SMALL_INT(count);
+}