py: Implement memoryview slice assignment.

Adds ability to do "memcpy" with memoryview objects, such as:
m1[0:3] = m2[2:5].
diff --git a/py/objarray.c b/py/objarray.c
index 404833e..9e6fd43 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -373,12 +373,12 @@
                 // Assign
                 mp_uint_t src_len;
                 void *src_items;
-                size_t item_sz = mp_binary_get_size('@', o->typecode, NULL);
+                size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
                 if (MP_OBJ_IS_TYPE(value, &mp_type_array) || MP_OBJ_IS_TYPE(value, &mp_type_bytearray)) {
                     mp_obj_array_t *src_slice = value;
-                    if (item_sz != mp_binary_get_size('@', src_slice->typecode, NULL)) {
+                    if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) {
                     compat_error:
-                        mp_not_implemented("lhs and rhs should be compatible");
+                        nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "lhs and rhs should be compatible"));
                     }
                     src_len = src_slice->len;
                     src_items = src_slice->items;
@@ -390,6 +390,13 @@
                     mp_get_buffer_raise(value, &bufinfo, MP_BUFFER_READ);
                     src_len = bufinfo.len;
                     src_items = bufinfo.buf;
+                } else if (MP_OBJ_IS_TYPE(value, &mp_type_memoryview)) {
+                    mp_obj_array_t *src_slice = value;
+                    if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) {
+                        goto compat_error;
+                    }
+                    src_len = src_slice->len;
+                    src_items = (uint8_t*)src_slice->items + (src_slice->free * item_sz);
                 } else {
                     mp_not_implemented("array/bytes required on right side");
                 }
@@ -397,6 +404,9 @@
                 // TODO: check src/dst compat
                 mp_int_t len_adj = src_len - (slice.stop - slice.start);
                 if (len_adj > 0) {
+                    if (o->base.type == &mp_type_memoryview) {
+                        goto compat_error;
+                    }
                     if (len_adj > o->free) {
                         // TODO: alloc policy; at the moment we go conservative
                         o->items = m_renew(byte, o->items, (o->len + o->free) * item_sz, (o->len + len_adj) * item_sz);
@@ -405,12 +415,20 @@
                     mp_seq_replace_slice_grow_inplace(o->items, o->len,
                         slice.start, slice.stop, src_items, src_len, len_adj, item_sz);
                 } else {
-                    mp_seq_replace_slice_no_grow(o->items, o->len,
-                        slice.start, slice.stop, src_items, src_len, item_sz);
-                    // Clear "freed" elements at the end of list
-                    // TODO: This is actually only needed for typecode=='O'
-                    mp_seq_clear(o->items, o->len + len_adj, o->len, item_sz);
-                    // TODO: alloc policy after shrinking
+                    if (o->base.type == &mp_type_memoryview) {
+                        if (len_adj != 0) {
+                            goto compat_error;
+                        }
+                        mp_seq_replace_slice_no_grow((uint8_t*)o->items + (o->free * item_sz), o->len,
+                            slice.start, slice.stop, src_items, src_len, item_sz);
+                    } else {
+                        mp_seq_replace_slice_no_grow(o->items, o->len,
+                            slice.start, slice.stop, src_items, src_len, item_sz);
+                        // Clear "freed" elements at the end of list
+                        // TODO: This is actually only needed for typecode=='O'
+                        mp_seq_clear(o->items, o->len + len_adj, o->len, item_sz);
+                        // TODO: alloc policy after shrinking
+                    }
                 }
                 o->len += len_adj;
                 return mp_const_none;