Port of MicroPython to the mbed platform. See micropython-repl for an interactive program.

Dependents:   micropython-repl

This a port of MicroPython to the mbed Classic platform.

This provides an interpreter running on the board's USB serial connection.

Getting Started

Import the micropython-repl program into your IDE workspace on developer.mbed.org. Compile and download to your board. Connect to the USB serial port in your usual manner. You should get a startup message similar to the following:

  MicroPython v1.7-155-gdddcdd8 on 2016-04-23; K64F with ARM
  Type "help()" for more information.
  >>>

Then you can start using micropython. For example:

  >>> from mbed import DigitalOut
  >>> from pins import LED1
  >>> led = DigitalOut(LED1)
  >>> led.write(1)

Requirements

You need approximately 100K of flash memory, so this will be no good for boards with smaller amounts of storage.

Caveats

This can be considered an alpha release of the port; things may not work; APIs may change in later releases. It is NOT an official part part the micropython project, so if anything doesn't work, blame me. If it does work, most of the credit is due to micropython.

  • Only a few of the mbed classes are available in micropython so far, and not all methods of those that are.
  • Only a few boards have their full range of pin names available; for others, only a few standard ones (USBTX, USBRX, LED1) are implemented.
  • The garbage collector is not yet implemented. The interpreter will gradually consume memory and then fail.
  • Exceptions from the mbed classes are not yet handled.
  • Asynchronous processing (e.g. events on inputs) is not supported.

Credits

  • Damien P. George and other contributors who created micropython.
  • Colin Hogben, author of this port.
Committer:
Colin Hogben
Date:
Wed Apr 27 22:11:29 2016 +0100
Revision:
10:33521d742af1
Parent:
0:5868e8752d44
Update README and version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pythontech 0:5868e8752d44 1 /*
pythontech 0:5868e8752d44 2 * This file is part of the Micro Python project, http://micropython.org/
pythontech 0:5868e8752d44 3 *
pythontech 0:5868e8752d44 4 * The MIT License (MIT)
pythontech 0:5868e8752d44 5 *
pythontech 0:5868e8752d44 6 * Copyright (c) 2013, 2014 Damien P. George
pythontech 0:5868e8752d44 7 *
pythontech 0:5868e8752d44 8 * Permission is hereby granted, free of charge, to any person obtaining a copy
pythontech 0:5868e8752d44 9 * of this software and associated documentation files (the "Software"), to deal
pythontech 0:5868e8752d44 10 * in the Software without restriction, including without limitation the rights
pythontech 0:5868e8752d44 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
pythontech 0:5868e8752d44 12 * copies of the Software, and to permit persons to whom the Software is
pythontech 0:5868e8752d44 13 * furnished to do so, subject to the following conditions:
pythontech 0:5868e8752d44 14 *
pythontech 0:5868e8752d44 15 * The above copyright notice and this permission notice shall be included in
pythontech 0:5868e8752d44 16 * all copies or substantial portions of the Software.
pythontech 0:5868e8752d44 17 *
pythontech 0:5868e8752d44 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
pythontech 0:5868e8752d44 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
pythontech 0:5868e8752d44 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
pythontech 0:5868e8752d44 21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
pythontech 0:5868e8752d44 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
pythontech 0:5868e8752d44 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
pythontech 0:5868e8752d44 24 * THE SOFTWARE.
pythontech 0:5868e8752d44 25 */
pythontech 0:5868e8752d44 26
pythontech 0:5868e8752d44 27 #include <string.h>
pythontech 0:5868e8752d44 28 #include <assert.h>
pythontech 0:5868e8752d44 29
pythontech 0:5868e8752d44 30 #include "py/nlr.h"
pythontech 0:5868e8752d44 31 #include "py/objlist.h"
pythontech 0:5868e8752d44 32 #include "py/runtime0.h"
pythontech 0:5868e8752d44 33 #include "py/runtime.h"
pythontech 0:5868e8752d44 34 #include "py/stackctrl.h"
pythontech 0:5868e8752d44 35
pythontech 0:5868e8752d44 36 STATIC mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, mp_uint_t cur);
pythontech 0:5868e8752d44 37 STATIC mp_obj_list_t *list_new(mp_uint_t n);
pythontech 0:5868e8752d44 38 STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in);
pythontech 0:5868e8752d44 39 STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args);
pythontech 0:5868e8752d44 40
pythontech 0:5868e8752d44 41 // TODO: Move to mpconfig.h
pythontech 0:5868e8752d44 42 #define LIST_MIN_ALLOC 4
pythontech 0:5868e8752d44 43
pythontech 0:5868e8752d44 44 /******************************************************************************/
pythontech 0:5868e8752d44 45 /* list */
pythontech 0:5868e8752d44 46
pythontech 0:5868e8752d44 47 STATIC void list_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
pythontech 0:5868e8752d44 48 mp_obj_list_t *o = MP_OBJ_TO_PTR(o_in);
pythontech 0:5868e8752d44 49 if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) {
pythontech 0:5868e8752d44 50 kind = PRINT_REPR;
pythontech 0:5868e8752d44 51 }
pythontech 0:5868e8752d44 52 mp_print_str(print, "[");
pythontech 0:5868e8752d44 53 for (mp_uint_t i = 0; i < o->len; i++) {
pythontech 0:5868e8752d44 54 if (i > 0) {
pythontech 0:5868e8752d44 55 mp_print_str(print, ", ");
pythontech 0:5868e8752d44 56 }
pythontech 0:5868e8752d44 57 mp_obj_print_helper(print, o->items[i], kind);
pythontech 0:5868e8752d44 58 }
pythontech 0:5868e8752d44 59 mp_print_str(print, "]");
pythontech 0:5868e8752d44 60 }
pythontech 0:5868e8752d44 61
pythontech 0:5868e8752d44 62 STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) {
pythontech 0:5868e8752d44 63 mp_obj_t iter = mp_getiter(iterable);
pythontech 0:5868e8752d44 64 mp_obj_t item;
pythontech 0:5868e8752d44 65 while ((item = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
pythontech 0:5868e8752d44 66 mp_obj_list_append(list, item);
pythontech 0:5868e8752d44 67 }
pythontech 0:5868e8752d44 68 return list;
pythontech 0:5868e8752d44 69 }
pythontech 0:5868e8752d44 70
pythontech 0:5868e8752d44 71 STATIC mp_obj_t list_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
pythontech 0:5868e8752d44 72 (void)type_in;
pythontech 0:5868e8752d44 73 mp_arg_check_num(n_args, n_kw, 0, 1, false);
pythontech 0:5868e8752d44 74
pythontech 0:5868e8752d44 75 switch (n_args) {
pythontech 0:5868e8752d44 76 case 0:
pythontech 0:5868e8752d44 77 // return a new, empty list
pythontech 0:5868e8752d44 78 return mp_obj_new_list(0, NULL);
pythontech 0:5868e8752d44 79
pythontech 0:5868e8752d44 80 case 1:
pythontech 0:5868e8752d44 81 default: {
pythontech 0:5868e8752d44 82 // make list from iterable
pythontech 0:5868e8752d44 83 // TODO: optimize list/tuple
pythontech 0:5868e8752d44 84 mp_obj_t list = mp_obj_new_list(0, NULL);
pythontech 0:5868e8752d44 85 return list_extend_from_iter(list, args[0]);
pythontech 0:5868e8752d44 86 }
pythontech 0:5868e8752d44 87 }
pythontech 0:5868e8752d44 88 }
pythontech 0:5868e8752d44 89
pythontech 0:5868e8752d44 90 // Don't pass MP_BINARY_OP_NOT_EQUAL here
pythontech 0:5868e8752d44 91 STATIC bool list_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) {
pythontech 0:5868e8752d44 92 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
pythontech 0:5868e8752d44 93 if (!MP_OBJ_IS_TYPE(another_in, &mp_type_list)) {
pythontech 0:5868e8752d44 94 return false;
pythontech 0:5868e8752d44 95 }
pythontech 0:5868e8752d44 96 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 97 mp_obj_list_t *another = MP_OBJ_TO_PTR(another_in);
pythontech 0:5868e8752d44 98
pythontech 0:5868e8752d44 99 return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len);
pythontech 0:5868e8752d44 100 }
pythontech 0:5868e8752d44 101
pythontech 0:5868e8752d44 102 STATIC mp_obj_t list_unary_op(mp_uint_t op, mp_obj_t self_in) {
pythontech 0:5868e8752d44 103 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 104 switch (op) {
pythontech 0:5868e8752d44 105 case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0);
pythontech 0:5868e8752d44 106 case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->len);
pythontech 0:5868e8752d44 107 default: return MP_OBJ_NULL; // op not supported
pythontech 0:5868e8752d44 108 }
pythontech 0:5868e8752d44 109 }
pythontech 0:5868e8752d44 110
pythontech 0:5868e8752d44 111 STATIC mp_obj_t list_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
pythontech 0:5868e8752d44 112 mp_obj_list_t *o = MP_OBJ_TO_PTR(lhs);
pythontech 0:5868e8752d44 113 switch (op) {
pythontech 0:5868e8752d44 114 case MP_BINARY_OP_ADD: {
pythontech 0:5868e8752d44 115 if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) {
pythontech 0:5868e8752d44 116 return MP_OBJ_NULL; // op not supported
pythontech 0:5868e8752d44 117 }
pythontech 0:5868e8752d44 118 mp_obj_list_t *p = MP_OBJ_TO_PTR(rhs);
pythontech 0:5868e8752d44 119 mp_obj_list_t *s = list_new(o->len + p->len);
pythontech 0:5868e8752d44 120 mp_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t);
pythontech 0:5868e8752d44 121 return MP_OBJ_FROM_PTR(s);
pythontech 0:5868e8752d44 122 }
pythontech 0:5868e8752d44 123 case MP_BINARY_OP_INPLACE_ADD: {
pythontech 0:5868e8752d44 124 list_extend(lhs, rhs);
pythontech 0:5868e8752d44 125 return lhs;
pythontech 0:5868e8752d44 126 }
pythontech 0:5868e8752d44 127 case MP_BINARY_OP_MULTIPLY: {
pythontech 0:5868e8752d44 128 mp_int_t n;
pythontech 0:5868e8752d44 129 if (!mp_obj_get_int_maybe(rhs, &n)) {
pythontech 0:5868e8752d44 130 return MP_OBJ_NULL; // op not supported
pythontech 0:5868e8752d44 131 }
pythontech 0:5868e8752d44 132 if (n < 0) {
pythontech 0:5868e8752d44 133 n = 0;
pythontech 0:5868e8752d44 134 }
pythontech 0:5868e8752d44 135 mp_obj_list_t *s = list_new(o->len * n);
pythontech 0:5868e8752d44 136 mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items);
pythontech 0:5868e8752d44 137 return MP_OBJ_FROM_PTR(s);
pythontech 0:5868e8752d44 138 }
pythontech 0:5868e8752d44 139 case MP_BINARY_OP_EQUAL:
pythontech 0:5868e8752d44 140 case MP_BINARY_OP_LESS:
pythontech 0:5868e8752d44 141 case MP_BINARY_OP_LESS_EQUAL:
pythontech 0:5868e8752d44 142 case MP_BINARY_OP_MORE:
pythontech 0:5868e8752d44 143 case MP_BINARY_OP_MORE_EQUAL:
pythontech 0:5868e8752d44 144 return mp_obj_new_bool(list_cmp_helper(op, lhs, rhs));
pythontech 0:5868e8752d44 145
pythontech 0:5868e8752d44 146 default:
pythontech 0:5868e8752d44 147 return MP_OBJ_NULL; // op not supported
pythontech 0:5868e8752d44 148 }
pythontech 0:5868e8752d44 149 }
pythontech 0:5868e8752d44 150
pythontech 0:5868e8752d44 151 STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
pythontech 0:5868e8752d44 152 if (value == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 153 // delete
pythontech 0:5868e8752d44 154 #if MICROPY_PY_BUILTINS_SLICE
pythontech 0:5868e8752d44 155 if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
pythontech 0:5868e8752d44 156 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 157 mp_bound_slice_t slice;
pythontech 0:5868e8752d44 158 if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
pythontech 0:5868e8752d44 159 assert(0);
pythontech 0:5868e8752d44 160 }
pythontech 0:5868e8752d44 161
pythontech 0:5868e8752d44 162 mp_int_t len_adj = slice.start - slice.stop;
pythontech 0:5868e8752d44 163 //printf("Len adj: %d\n", len_adj);
pythontech 0:5868e8752d44 164 assert(len_adj <= 0);
pythontech 0:5868e8752d44 165 mp_seq_replace_slice_no_grow(self->items, self->len, slice.start, slice.stop, self->items/*NULL*/, 0, sizeof(*self->items));
pythontech 0:5868e8752d44 166 // Clear "freed" elements at the end of list
pythontech 0:5868e8752d44 167 mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items));
pythontech 0:5868e8752d44 168 self->len += len_adj;
pythontech 0:5868e8752d44 169 return mp_const_none;
pythontech 0:5868e8752d44 170 }
pythontech 0:5868e8752d44 171 #endif
pythontech 0:5868e8752d44 172 mp_obj_t args[2] = {self_in, index};
pythontech 0:5868e8752d44 173 list_pop(2, args);
pythontech 0:5868e8752d44 174 return mp_const_none;
pythontech 0:5868e8752d44 175 } else if (value == MP_OBJ_SENTINEL) {
pythontech 0:5868e8752d44 176 // load
pythontech 0:5868e8752d44 177 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 178 #if MICROPY_PY_BUILTINS_SLICE
pythontech 0:5868e8752d44 179 if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
pythontech 0:5868e8752d44 180 mp_bound_slice_t slice;
pythontech 0:5868e8752d44 181 if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
pythontech 0:5868e8752d44 182 return mp_seq_extract_slice(self->len, self->items, &slice);
pythontech 0:5868e8752d44 183 }
pythontech 0:5868e8752d44 184 mp_obj_list_t *res = list_new(slice.stop - slice.start);
pythontech 0:5868e8752d44 185 mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t);
pythontech 0:5868e8752d44 186 return MP_OBJ_FROM_PTR(res);
pythontech 0:5868e8752d44 187 }
pythontech 0:5868e8752d44 188 #endif
pythontech 0:5868e8752d44 189 mp_uint_t index_val = mp_get_index(self->base.type, self->len, index, false);
pythontech 0:5868e8752d44 190 return self->items[index_val];
pythontech 0:5868e8752d44 191 } else {
pythontech 0:5868e8752d44 192 #if MICROPY_PY_BUILTINS_SLICE
pythontech 0:5868e8752d44 193 if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
pythontech 0:5868e8752d44 194 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 195 assert(MP_OBJ_IS_TYPE(value, &mp_type_list));
pythontech 0:5868e8752d44 196 mp_obj_list_t *slice = MP_OBJ_TO_PTR(value);
pythontech 0:5868e8752d44 197 mp_bound_slice_t slice_out;
pythontech 0:5868e8752d44 198 if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) {
pythontech 0:5868e8752d44 199 assert(0);
pythontech 0:5868e8752d44 200 }
pythontech 0:5868e8752d44 201 mp_int_t len_adj = slice->len - (slice_out.stop - slice_out.start);
pythontech 0:5868e8752d44 202 //printf("Len adj: %d\n", len_adj);
pythontech 0:5868e8752d44 203 if (len_adj > 0) {
pythontech 0:5868e8752d44 204 if (self->len + len_adj > self->alloc) {
pythontech 0:5868e8752d44 205 // TODO: Might optimize memory copies here by checking if block can
pythontech 0:5868e8752d44 206 // be grown inplace or not
pythontech 0:5868e8752d44 207 self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + len_adj);
pythontech 0:5868e8752d44 208 self->alloc = self->len + len_adj;
pythontech 0:5868e8752d44 209 }
pythontech 0:5868e8752d44 210 mp_seq_replace_slice_grow_inplace(self->items, self->len,
pythontech 0:5868e8752d44 211 slice_out.start, slice_out.stop, slice->items, slice->len, len_adj, sizeof(*self->items));
pythontech 0:5868e8752d44 212 } else {
pythontech 0:5868e8752d44 213 mp_seq_replace_slice_no_grow(self->items, self->len,
pythontech 0:5868e8752d44 214 slice_out.start, slice_out.stop, slice->items, slice->len, sizeof(*self->items));
pythontech 0:5868e8752d44 215 // Clear "freed" elements at the end of list
pythontech 0:5868e8752d44 216 mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items));
pythontech 0:5868e8752d44 217 // TODO: apply allocation policy re: alloc_size
pythontech 0:5868e8752d44 218 }
pythontech 0:5868e8752d44 219 self->len += len_adj;
pythontech 0:5868e8752d44 220 return mp_const_none;
pythontech 0:5868e8752d44 221 }
pythontech 0:5868e8752d44 222 #endif
pythontech 0:5868e8752d44 223 mp_obj_list_store(self_in, index, value);
pythontech 0:5868e8752d44 224 return mp_const_none;
pythontech 0:5868e8752d44 225 }
pythontech 0:5868e8752d44 226 }
pythontech 0:5868e8752d44 227
pythontech 0:5868e8752d44 228 STATIC mp_obj_t list_getiter(mp_obj_t o_in) {
pythontech 0:5868e8752d44 229 return mp_obj_new_list_iterator(o_in, 0);
pythontech 0:5868e8752d44 230 }
pythontech 0:5868e8752d44 231
pythontech 0:5868e8752d44 232 mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
pythontech 0:5868e8752d44 233 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
pythontech 0:5868e8752d44 234 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 235 if (self->len >= self->alloc) {
pythontech 0:5868e8752d44 236 self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc * 2);
pythontech 0:5868e8752d44 237 self->alloc *= 2;
pythontech 0:5868e8752d44 238 mp_seq_clear(self->items, self->len + 1, self->alloc, sizeof(*self->items));
pythontech 0:5868e8752d44 239 }
pythontech 0:5868e8752d44 240 self->items[self->len++] = arg;
pythontech 0:5868e8752d44 241 return mp_const_none; // return None, as per CPython
pythontech 0:5868e8752d44 242 }
pythontech 0:5868e8752d44 243
pythontech 0:5868e8752d44 244 STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) {
pythontech 0:5868e8752d44 245 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
pythontech 0:5868e8752d44 246 if (MP_OBJ_IS_TYPE(arg_in, &mp_type_list)) {
pythontech 0:5868e8752d44 247 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 248 mp_obj_list_t *arg = MP_OBJ_TO_PTR(arg_in);
pythontech 0:5868e8752d44 249
pythontech 0:5868e8752d44 250 if (self->len + arg->len > self->alloc) {
pythontech 0:5868e8752d44 251 // TODO: use alloc policy for "4"
pythontech 0:5868e8752d44 252 self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4);
pythontech 0:5868e8752d44 253 self->alloc = self->len + arg->len + 4;
pythontech 0:5868e8752d44 254 mp_seq_clear(self->items, self->len + arg->len, self->alloc, sizeof(*self->items));
pythontech 0:5868e8752d44 255 }
pythontech 0:5868e8752d44 256
pythontech 0:5868e8752d44 257 memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len);
pythontech 0:5868e8752d44 258 self->len += arg->len;
pythontech 0:5868e8752d44 259 } else {
pythontech 0:5868e8752d44 260 list_extend_from_iter(self_in, arg_in);
pythontech 0:5868e8752d44 261 }
pythontech 0:5868e8752d44 262 return mp_const_none; // return None, as per CPython
pythontech 0:5868e8752d44 263 }
pythontech 0:5868e8752d44 264
pythontech 0:5868e8752d44 265 STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) {
pythontech 0:5868e8752d44 266 assert(1 <= n_args && n_args <= 2);
pythontech 0:5868e8752d44 267 assert(MP_OBJ_IS_TYPE(args[0], &mp_type_list));
pythontech 0:5868e8752d44 268 mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]);
pythontech 0:5868e8752d44 269 if (self->len == 0) {
pythontech 0:5868e8752d44 270 nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "pop from empty list"));
pythontech 0:5868e8752d44 271 }
pythontech 0:5868e8752d44 272 mp_uint_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false);
pythontech 0:5868e8752d44 273 mp_obj_t ret = self->items[index];
pythontech 0:5868e8752d44 274 self->len -= 1;
pythontech 0:5868e8752d44 275 memmove(self->items + index, self->items + index + 1, (self->len - index) * sizeof(mp_obj_t));
pythontech 0:5868e8752d44 276 // Clear stale pointer from slot which just got freed to prevent GC issues
pythontech 0:5868e8752d44 277 self->items[self->len] = MP_OBJ_NULL;
pythontech 0:5868e8752d44 278 if (self->alloc > LIST_MIN_ALLOC && self->alloc > 2 * self->len) {
pythontech 0:5868e8752d44 279 self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc/2);
pythontech 0:5868e8752d44 280 self->alloc /= 2;
pythontech 0:5868e8752d44 281 }
pythontech 0:5868e8752d44 282 return ret;
pythontech 0:5868e8752d44 283 }
pythontech 0:5868e8752d44 284
pythontech 0:5868e8752d44 285 STATIC void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, mp_obj_t binop_less_result) {
pythontech 0:5868e8752d44 286 MP_STACK_CHECK();
pythontech 0:5868e8752d44 287 while (head < tail) {
pythontech 0:5868e8752d44 288 mp_obj_t *h = head - 1;
pythontech 0:5868e8752d44 289 mp_obj_t *t = tail;
pythontech 0:5868e8752d44 290 mp_obj_t v = key_fn == MP_OBJ_NULL ? tail[0] : mp_call_function_1(key_fn, tail[0]); // get pivot using key_fn
pythontech 0:5868e8752d44 291 for (;;) {
pythontech 0:5868e8752d44 292 do ++h; while (h < t && mp_binary_op(MP_BINARY_OP_LESS, key_fn == MP_OBJ_NULL ? h[0] : mp_call_function_1(key_fn, h[0]), v) == binop_less_result);
pythontech 0:5868e8752d44 293 do --t; while (h < t && mp_binary_op(MP_BINARY_OP_LESS, v, key_fn == MP_OBJ_NULL ? t[0] : mp_call_function_1(key_fn, t[0])) == binop_less_result);
pythontech 0:5868e8752d44 294 if (h >= t) break;
pythontech 0:5868e8752d44 295 mp_obj_t x = h[0];
pythontech 0:5868e8752d44 296 h[0] = t[0];
pythontech 0:5868e8752d44 297 t[0] = x;
pythontech 0:5868e8752d44 298 }
pythontech 0:5868e8752d44 299 mp_obj_t x = h[0];
pythontech 0:5868e8752d44 300 h[0] = tail[0];
pythontech 0:5868e8752d44 301 tail[0] = x;
pythontech 0:5868e8752d44 302 // do the smaller recursive call first, to keep stack within O(log(N))
pythontech 0:5868e8752d44 303 if (t - head < tail - h - 1) {
pythontech 0:5868e8752d44 304 mp_quicksort(head, t, key_fn, binop_less_result);
pythontech 0:5868e8752d44 305 head = h + 1;
pythontech 0:5868e8752d44 306 } else {
pythontech 0:5868e8752d44 307 mp_quicksort(h + 1, tail, key_fn, binop_less_result);
pythontech 0:5868e8752d44 308 tail = t;
pythontech 0:5868e8752d44 309 }
pythontech 0:5868e8752d44 310 }
pythontech 0:5868e8752d44 311 }
pythontech 0:5868e8752d44 312
pythontech 0:5868e8752d44 313 // TODO Python defines sort to be stable but ours is not
pythontech 0:5868e8752d44 314 mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
pythontech 0:5868e8752d44 315 static const mp_arg_t allowed_args[] = {
pythontech 0:5868e8752d44 316 { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
pythontech 0:5868e8752d44 317 { MP_QSTR_reverse, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
pythontech 0:5868e8752d44 318 };
pythontech 0:5868e8752d44 319
pythontech 0:5868e8752d44 320 // parse args
pythontech 0:5868e8752d44 321 struct {
pythontech 0:5868e8752d44 322 mp_arg_val_t key, reverse;
pythontech 0:5868e8752d44 323 } args;
pythontech 0:5868e8752d44 324 mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
pythontech 0:5868e8752d44 325 MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
pythontech 0:5868e8752d44 326
pythontech 0:5868e8752d44 327 assert(MP_OBJ_IS_TYPE(pos_args[0], &mp_type_list));
pythontech 0:5868e8752d44 328 mp_obj_list_t *self = MP_OBJ_TO_PTR(pos_args[0]);
pythontech 0:5868e8752d44 329
pythontech 0:5868e8752d44 330 if (self->len > 1) {
pythontech 0:5868e8752d44 331 mp_quicksort(self->items, self->items + self->len - 1,
pythontech 0:5868e8752d44 332 args.key.u_obj == mp_const_none ? MP_OBJ_NULL : args.key.u_obj,
pythontech 0:5868e8752d44 333 args.reverse.u_bool ? mp_const_false : mp_const_true);
pythontech 0:5868e8752d44 334 }
pythontech 0:5868e8752d44 335
pythontech 0:5868e8752d44 336 return mp_const_none;
pythontech 0:5868e8752d44 337 }
pythontech 0:5868e8752d44 338
pythontech 0:5868e8752d44 339 STATIC mp_obj_t list_clear(mp_obj_t self_in) {
pythontech 0:5868e8752d44 340 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
pythontech 0:5868e8752d44 341 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 342 self->len = 0;
pythontech 0:5868e8752d44 343 self->items = m_renew(mp_obj_t, self->items, self->alloc, LIST_MIN_ALLOC);
pythontech 0:5868e8752d44 344 self->alloc = LIST_MIN_ALLOC;
pythontech 0:5868e8752d44 345 mp_seq_clear(self->items, 0, self->alloc, sizeof(*self->items));
pythontech 0:5868e8752d44 346 return mp_const_none;
pythontech 0:5868e8752d44 347 }
pythontech 0:5868e8752d44 348
pythontech 0:5868e8752d44 349 STATIC mp_obj_t list_copy(mp_obj_t self_in) {
pythontech 0:5868e8752d44 350 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
pythontech 0:5868e8752d44 351 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 352 return mp_obj_new_list(self->len, self->items);
pythontech 0:5868e8752d44 353 }
pythontech 0:5868e8752d44 354
pythontech 0:5868e8752d44 355 STATIC mp_obj_t list_count(mp_obj_t self_in, mp_obj_t value) {
pythontech 0:5868e8752d44 356 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
pythontech 0:5868e8752d44 357 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 358 return mp_seq_count_obj(self->items, self->len, value);
pythontech 0:5868e8752d44 359 }
pythontech 0:5868e8752d44 360
pythontech 0:5868e8752d44 361 STATIC mp_obj_t list_index(size_t n_args, const mp_obj_t *args) {
pythontech 0:5868e8752d44 362 assert(2 <= n_args && n_args <= 4);
pythontech 0:5868e8752d44 363 assert(MP_OBJ_IS_TYPE(args[0], &mp_type_list));
pythontech 0:5868e8752d44 364 mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]);
pythontech 0:5868e8752d44 365 return mp_seq_index_obj(self->items, self->len, n_args, args);
pythontech 0:5868e8752d44 366 }
pythontech 0:5868e8752d44 367
pythontech 0:5868e8752d44 368 STATIC mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) {
pythontech 0:5868e8752d44 369 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
pythontech 0:5868e8752d44 370 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 371 // insert has its own strange index logic
pythontech 0:5868e8752d44 372 mp_int_t index = MP_OBJ_SMALL_INT_VALUE(idx);
pythontech 0:5868e8752d44 373 if (index < 0) {
pythontech 0:5868e8752d44 374 index += self->len;
pythontech 0:5868e8752d44 375 }
pythontech 0:5868e8752d44 376 if (index < 0) {
pythontech 0:5868e8752d44 377 index = 0;
pythontech 0:5868e8752d44 378 }
pythontech 0:5868e8752d44 379 if ((mp_uint_t)index > self->len) {
pythontech 0:5868e8752d44 380 index = self->len;
pythontech 0:5868e8752d44 381 }
pythontech 0:5868e8752d44 382
pythontech 0:5868e8752d44 383 mp_obj_list_append(self_in, mp_const_none);
pythontech 0:5868e8752d44 384
pythontech 0:5868e8752d44 385 for (mp_int_t i = self->len-1; i > index; i--) {
pythontech 0:5868e8752d44 386 self->items[i] = self->items[i-1];
pythontech 0:5868e8752d44 387 }
pythontech 0:5868e8752d44 388 self->items[index] = obj;
pythontech 0:5868e8752d44 389
pythontech 0:5868e8752d44 390 return mp_const_none;
pythontech 0:5868e8752d44 391 }
pythontech 0:5868e8752d44 392
pythontech 0:5868e8752d44 393 mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value) {
pythontech 0:5868e8752d44 394 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
pythontech 0:5868e8752d44 395 mp_obj_t args[] = {self_in, value};
pythontech 0:5868e8752d44 396 args[1] = list_index(2, args);
pythontech 0:5868e8752d44 397 list_pop(2, args);
pythontech 0:5868e8752d44 398
pythontech 0:5868e8752d44 399 return mp_const_none;
pythontech 0:5868e8752d44 400 }
pythontech 0:5868e8752d44 401
pythontech 0:5868e8752d44 402 STATIC mp_obj_t list_reverse(mp_obj_t self_in) {
pythontech 0:5868e8752d44 403 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
pythontech 0:5868e8752d44 404 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 405
pythontech 0:5868e8752d44 406 mp_int_t len = self->len;
pythontech 0:5868e8752d44 407 for (mp_int_t i = 0; i < len/2; i++) {
pythontech 0:5868e8752d44 408 mp_obj_t a = self->items[i];
pythontech 0:5868e8752d44 409 self->items[i] = self->items[len-i-1];
pythontech 0:5868e8752d44 410 self->items[len-i-1] = a;
pythontech 0:5868e8752d44 411 }
pythontech 0:5868e8752d44 412
pythontech 0:5868e8752d44 413 return mp_const_none;
pythontech 0:5868e8752d44 414 }
pythontech 0:5868e8752d44 415
pythontech 0:5868e8752d44 416 STATIC MP_DEFINE_CONST_FUN_OBJ_2(list_append_obj, mp_obj_list_append);
pythontech 0:5868e8752d44 417 STATIC MP_DEFINE_CONST_FUN_OBJ_2(list_extend_obj, list_extend);
pythontech 0:5868e8752d44 418 STATIC MP_DEFINE_CONST_FUN_OBJ_1(list_clear_obj, list_clear);
pythontech 0:5868e8752d44 419 STATIC MP_DEFINE_CONST_FUN_OBJ_1(list_copy_obj, list_copy);
pythontech 0:5868e8752d44 420 STATIC MP_DEFINE_CONST_FUN_OBJ_2(list_count_obj, list_count);
pythontech 0:5868e8752d44 421 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(list_index_obj, 2, 4, list_index);
pythontech 0:5868e8752d44 422 STATIC MP_DEFINE_CONST_FUN_OBJ_3(list_insert_obj, list_insert);
pythontech 0:5868e8752d44 423 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(list_pop_obj, 1, 2, list_pop);
pythontech 0:5868e8752d44 424 STATIC MP_DEFINE_CONST_FUN_OBJ_2(list_remove_obj, mp_obj_list_remove);
pythontech 0:5868e8752d44 425 STATIC MP_DEFINE_CONST_FUN_OBJ_1(list_reverse_obj, list_reverse);
pythontech 0:5868e8752d44 426 STATIC MP_DEFINE_CONST_FUN_OBJ_KW(list_sort_obj, 1, mp_obj_list_sort);
pythontech 0:5868e8752d44 427
pythontech 0:5868e8752d44 428 STATIC const mp_rom_map_elem_t list_locals_dict_table[] = {
pythontech 0:5868e8752d44 429 { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&list_append_obj) },
pythontech 0:5868e8752d44 430 { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&list_clear_obj) },
pythontech 0:5868e8752d44 431 { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&list_copy_obj) },
pythontech 0:5868e8752d44 432 { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&list_count_obj) },
pythontech 0:5868e8752d44 433 { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&list_extend_obj) },
pythontech 0:5868e8752d44 434 { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&list_index_obj) },
pythontech 0:5868e8752d44 435 { MP_ROM_QSTR(MP_QSTR_insert), MP_ROM_PTR(&list_insert_obj) },
pythontech 0:5868e8752d44 436 { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&list_pop_obj) },
pythontech 0:5868e8752d44 437 { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&list_remove_obj) },
pythontech 0:5868e8752d44 438 { MP_ROM_QSTR(MP_QSTR_reverse), MP_ROM_PTR(&list_reverse_obj) },
pythontech 0:5868e8752d44 439 { MP_ROM_QSTR(MP_QSTR_sort), MP_ROM_PTR(&list_sort_obj) },
pythontech 0:5868e8752d44 440 };
pythontech 0:5868e8752d44 441
pythontech 0:5868e8752d44 442 STATIC MP_DEFINE_CONST_DICT(list_locals_dict, list_locals_dict_table);
pythontech 0:5868e8752d44 443
pythontech 0:5868e8752d44 444 const mp_obj_type_t mp_type_list = {
pythontech 0:5868e8752d44 445 { &mp_type_type },
pythontech 0:5868e8752d44 446 .name = MP_QSTR_list,
pythontech 0:5868e8752d44 447 .print = list_print,
pythontech 0:5868e8752d44 448 .make_new = list_make_new,
pythontech 0:5868e8752d44 449 .unary_op = list_unary_op,
pythontech 0:5868e8752d44 450 .binary_op = list_binary_op,
pythontech 0:5868e8752d44 451 .subscr = list_subscr,
pythontech 0:5868e8752d44 452 .getiter = list_getiter,
pythontech 0:5868e8752d44 453 .locals_dict = (mp_obj_dict_t*)&list_locals_dict,
pythontech 0:5868e8752d44 454 };
pythontech 0:5868e8752d44 455
pythontech 0:5868e8752d44 456 void mp_obj_list_init(mp_obj_list_t *o, mp_uint_t n) {
pythontech 0:5868e8752d44 457 o->base.type = &mp_type_list;
pythontech 0:5868e8752d44 458 o->alloc = n < LIST_MIN_ALLOC ? LIST_MIN_ALLOC : n;
pythontech 0:5868e8752d44 459 o->len = n;
pythontech 0:5868e8752d44 460 o->items = m_new(mp_obj_t, o->alloc);
pythontech 0:5868e8752d44 461 mp_seq_clear(o->items, n, o->alloc, sizeof(*o->items));
pythontech 0:5868e8752d44 462 }
pythontech 0:5868e8752d44 463
pythontech 0:5868e8752d44 464 STATIC mp_obj_list_t *list_new(mp_uint_t n) {
pythontech 0:5868e8752d44 465 mp_obj_list_t *o = m_new_obj(mp_obj_list_t);
pythontech 0:5868e8752d44 466 mp_obj_list_init(o, n);
pythontech 0:5868e8752d44 467 return o;
pythontech 0:5868e8752d44 468 }
pythontech 0:5868e8752d44 469
pythontech 0:5868e8752d44 470 mp_obj_t mp_obj_new_list(mp_uint_t n, mp_obj_t *items) {
pythontech 0:5868e8752d44 471 mp_obj_list_t *o = list_new(n);
pythontech 0:5868e8752d44 472 if (items != NULL) {
pythontech 0:5868e8752d44 473 for (mp_uint_t i = 0; i < n; i++) {
pythontech 0:5868e8752d44 474 o->items[i] = items[i];
pythontech 0:5868e8752d44 475 }
pythontech 0:5868e8752d44 476 }
pythontech 0:5868e8752d44 477 return MP_OBJ_FROM_PTR(o);
pythontech 0:5868e8752d44 478 }
pythontech 0:5868e8752d44 479
pythontech 0:5868e8752d44 480 void mp_obj_list_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items) {
pythontech 0:5868e8752d44 481 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 482 *len = self->len;
pythontech 0:5868e8752d44 483 *items = self->items;
pythontech 0:5868e8752d44 484 }
pythontech 0:5868e8752d44 485
pythontech 0:5868e8752d44 486 void mp_obj_list_set_len(mp_obj_t self_in, mp_uint_t len) {
pythontech 0:5868e8752d44 487 // trust that the caller knows what it's doing
pythontech 0:5868e8752d44 488 // TODO realloc if len got much smaller than alloc
pythontech 0:5868e8752d44 489 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 490 self->len = len;
pythontech 0:5868e8752d44 491 }
pythontech 0:5868e8752d44 492
pythontech 0:5868e8752d44 493 void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
pythontech 0:5868e8752d44 494 mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 495 mp_uint_t i = mp_get_index(self->base.type, self->len, index, false);
pythontech 0:5868e8752d44 496 self->items[i] = value;
pythontech 0:5868e8752d44 497 }
pythontech 0:5868e8752d44 498
pythontech 0:5868e8752d44 499 /******************************************************************************/
pythontech 0:5868e8752d44 500 /* list iterator */
pythontech 0:5868e8752d44 501
pythontech 0:5868e8752d44 502 typedef struct _mp_obj_list_it_t {
pythontech 0:5868e8752d44 503 mp_obj_base_t base;
pythontech 0:5868e8752d44 504 mp_fun_1_t iternext;
pythontech 0:5868e8752d44 505 mp_obj_t list;
pythontech 0:5868e8752d44 506 mp_uint_t cur;
pythontech 0:5868e8752d44 507 } mp_obj_list_it_t;
pythontech 0:5868e8752d44 508
pythontech 0:5868e8752d44 509 STATIC mp_obj_t list_it_iternext(mp_obj_t self_in) {
pythontech 0:5868e8752d44 510 mp_obj_list_it_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 511 mp_obj_list_t *list = MP_OBJ_TO_PTR(self->list);
pythontech 0:5868e8752d44 512 if (self->cur < list->len) {
pythontech 0:5868e8752d44 513 mp_obj_t o_out = list->items[self->cur];
pythontech 0:5868e8752d44 514 self->cur += 1;
pythontech 0:5868e8752d44 515 return o_out;
pythontech 0:5868e8752d44 516 } else {
pythontech 0:5868e8752d44 517 return MP_OBJ_STOP_ITERATION;
pythontech 0:5868e8752d44 518 }
pythontech 0:5868e8752d44 519 }
pythontech 0:5868e8752d44 520
pythontech 0:5868e8752d44 521 mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, mp_uint_t cur) {
pythontech 0:5868e8752d44 522 mp_obj_list_it_t *o = m_new_obj(mp_obj_list_it_t);
pythontech 0:5868e8752d44 523 o->base.type = &mp_type_polymorph_iter;
pythontech 0:5868e8752d44 524 o->iternext = list_it_iternext;
pythontech 0:5868e8752d44 525 o->list = list;
pythontech 0:5868e8752d44 526 o->cur = cur;
pythontech 0:5868e8752d44 527 return MP_OBJ_FROM_PTR(o);
pythontech 0:5868e8752d44 528 }