summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-02-02 13:13:29 +0000
committerDamien George <damien.p.george@gmail.com>2014-02-02 13:13:29 +0000
commit09e1f43200ec28082456042a58d9f39f483f3ad0 (patch)
treea61fff4a0fbad891177d64bf311c9cb0882b4e1b /py
parentcd82e02e84df5f9f2f3082d865beae25217af2a1 (diff)
parentea2509d92cbb222854ceb0b323b616b807dd221b (diff)
downloadmicropython-09e1f43200ec28082456042a58d9f39f483f3ad0.tar.gz
micropython-09e1f43200ec28082456042a58d9f39f483f3ad0.zip
Merge branch 'master' of github.com:micropython/micropython
Diffstat (limited to 'py')
-rw-r--r--py/obj.h3
-rw-r--r--py/objlist.c12
-rw-r--r--py/objstr.c34
-rw-r--r--py/objtuple.c13
-rw-r--r--py/runtime.c26
-rw-r--r--py/sequence.c68
6 files changed, 130 insertions, 26 deletions
diff --git a/py/obj.h b/py/obj.h
index 0680e6fb1c..ca3ab1af6a 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -395,3 +395,6 @@ typedef struct _mp_obj_classmethod_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))
+bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, uint len2);
diff --git a/py/objlist.c b/py/objlist.c
index b28ca81279..59a4ad6b12 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -136,7 +136,17 @@ static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
switch (op) {
case RT_BINARY_OP_SUBSCR:
{
- // list load
+#if MICROPY_ENABLE_SLICE
+ if (MP_OBJ_IS_TYPE(rhs, &slice_type)) {
+ machine_uint_t start, stop;
+ if (!m_seq_get_fast_slice_indexes(o->len, rhs, &start, &stop)) {
+ assert(0);
+ }
+ mp_obj_list_t *res = list_new(stop - start);
+ m_seq_copy(res->items, o->items + start, res->len, mp_obj_t);
+ return res;
+ }
+#endif
uint index = mp_get_index(o->base.type, o->len, rhs);
return o->items[index];
}
diff --git a/py/objstr.c b/py/objstr.c
index 3f6aa483e2..03602b6ec7 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -115,25 +115,9 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
}
#if MICROPY_ENABLE_SLICE
} else if (MP_OBJ_IS_TYPE(rhs_in, &slice_type)) {
- machine_int_t start, stop, step;
- mp_obj_slice_get(rhs_in, &start, &stop, &step);
- assert(step == 1);
- if (start < 0) {
- start = lhs_len + start;
- if (start < 0) {
- start = 0;
- }
- } else if (start > lhs_len) {
- start = lhs_len;
- }
- if (stop <= 0) {
- stop = lhs_len + stop;
- // CPython returns empty string in such case
- if (stop < 0) {
- stop = start;
- }
- } else if (stop > lhs_len) {
- stop = lhs_len;
+ machine_uint_t start, stop;
+ if (!m_seq_get_fast_slice_indexes(lhs_len, rhs_in, &start, &stop)) {
+ assert(0);
}
return mp_obj_new_str(lhs_data + start, stop - start, false);
#endif
@@ -187,6 +171,18 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_seq_multiply(lhs_data, sizeof(*lhs_data), lhs_len, n, data);
return mp_obj_str_builder_end(s);
}
+
+ // These 2 are never passed here, dealt with as a special case in rt_binary_op().
+ //case RT_BINARY_OP_EQUAL:
+ //case RT_BINARY_OP_NOT_EQUAL:
+ case RT_BINARY_OP_LESS:
+ case RT_BINARY_OP_LESS_EQUAL:
+ case RT_BINARY_OP_MORE:
+ case RT_BINARY_OP_MORE_EQUAL:
+ if (MP_OBJ_IS_STR(rhs_in)) {
+ GET_STR_DATA_LEN(rhs_in, rhs_data, rhs_len);
+ return MP_BOOL(mp_seq_cmp_bytes(op, lhs_data, lhs_len, rhs_data, rhs_len));
+ }
}
return MP_OBJ_NULL; // op not supported
diff --git a/py/objtuple.c b/py/objtuple.c
index 5f1744ea30..3e5041c9dd 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -1,3 +1,4 @@
+#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
@@ -87,7 +88,17 @@ static mp_obj_t tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
switch (op) {
case RT_BINARY_OP_SUBSCR:
{
- // tuple load
+#if MICROPY_ENABLE_SLICE
+ if (MP_OBJ_IS_TYPE(rhs, &slice_type)) {
+ machine_uint_t start, stop;
+ if (!m_seq_get_fast_slice_indexes(o->len, rhs, &start, &stop)) {
+ assert(0);
+ }
+ mp_obj_tuple_t *res = mp_obj_new_tuple(stop - start, NULL);
+ m_seq_copy(res->items, o->items + start, res->len, mp_obj_t);
+ return res;
+ }
+#endif
uint index = mp_get_index(o->base.type, o->len, rhs);
return o->items[index];
}
diff --git a/py/runtime.c b/py/runtime.c
index b524e65208..07be34d017 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -768,8 +768,8 @@ mp_obj_t rt_store_set(mp_obj_t set, mp_obj_t item) {
// unpacked items are stored in reverse order into the array pointed to by items
void rt_unpack_sequence(mp_obj_t seq_in, uint num, mp_obj_t *items) {
+ uint seq_len;
if (MP_OBJ_IS_TYPE(seq_in, &tuple_type) || MP_OBJ_IS_TYPE(seq_in, &list_type)) {
- uint seq_len;
mp_obj_t *seq_items;
if (MP_OBJ_IS_TYPE(seq_in, &tuple_type)) {
mp_obj_tuple_get(seq_in, &seq_len, &seq_items);
@@ -777,17 +777,33 @@ void rt_unpack_sequence(mp_obj_t seq_in, uint num, mp_obj_t *items) {
mp_obj_list_get(seq_in, &seq_len, &seq_items);
}
if (seq_len < num) {
- nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "need more than %d values to unpack", (void*)(machine_uint_t)seq_len));
+ goto too_short;
} else if (seq_len > num) {
- nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "too many values to unpack (expected %d)", (void*)(machine_uint_t)num));
+ goto too_long;
}
for (uint i = 0; i < num; i++) {
items[i] = seq_items[num - 1 - i];
}
} else {
- // TODO call rt_getiter and extract via rt_iternext
- nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(seq_in)));
+ mp_obj_t iterable = rt_getiter(seq_in);
+
+ for (seq_len = 0; seq_len < num; seq_len++) {
+ mp_obj_t el = rt_iternext(iterable);
+ if (el == mp_const_stop_iteration) {
+ goto too_short;
+ }
+ items[num - 1 - seq_len] = el;
+ }
+ if (rt_iternext(iterable) != mp_const_stop_iteration) {
+ goto too_long;
+ }
}
+ return;
+
+too_short:
+ nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "need more than %d values to unpack", seq_len));
+too_long:
+ nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "too many values to unpack (expected %d)", num));
}
mp_obj_t rt_build_map(int n_args) {
diff --git a/py/sequence.c b/py/sequence.c
index 56718c6f85..74b4fcfdf8 100644
--- a/py/sequence.c
+++ b/py/sequence.c
@@ -14,6 +14,8 @@
// Helpers for sequence types
+#define SWAP(type, var1, var2) { type t = var2; var2 = var1; var1 = t; }
+
// Implements backend of sequence * integer operation. Assumes elements are
// memory-adjacent in sequence.
void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest) {
@@ -23,3 +25,69 @@ void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void
dest = (char*)dest + copy_sz;
}
}
+
+bool m_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, machine_uint_t *begin, machine_uint_t *end) {
+ machine_int_t start, stop, step;
+ mp_obj_slice_get(slice, &start, &stop, &step);
+ if (step != 1) {
+ return false;
+ }
+
+ // Unlike subscription, out-of-bounds slice indexes are never error
+ if (start < 0) {
+ start = len + start;
+ if (start < 0) {
+ start = 0;
+ }
+ } else if (start > len) {
+ start = len;
+ }
+ if (stop <= 0) {
+ stop = len + stop;
+ // CPython returns empty sequence in such case
+ if (stop < 0) {
+ stop = start;
+ }
+ } else if (stop > len) {
+ stop = len;
+ }
+ *begin = start;
+ *end = stop;
+ return true;
+}
+
+// Special-case comparison function for sequences of bytes
+// Don't pass RT_BINARY_OP_NOT_EQUAL here
+bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, uint len2) {
+ // Let's deal only with > & >=
+ if (op == RT_BINARY_OP_LESS || op == RT_BINARY_OP_LESS_EQUAL) {
+ SWAP(const byte*, data1, data2);
+ SWAP(uint, len1, len2);
+ if (op == RT_BINARY_OP_LESS) {
+ op = RT_BINARY_OP_MORE;
+ } else {
+ op = RT_BINARY_OP_MORE_EQUAL;
+ }
+ }
+ uint min_len = len1 < len2 ? len1 : len2;
+ int res = memcmp(data1, data2, min_len);
+ if (res < 0) {
+ return false;
+ }
+ if (res > 0) {
+ return true;
+ }
+
+ // If we had tie in the last element...
+ // ... 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;
+}