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:
pythontech
Date:
Sat Apr 16 17:11:56 2016 +0000
Revision:
0:5868e8752d44
Child:
2:c89e95946844
Split off library from repl

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-2015 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 "py/obj.h"
pythontech 0:5868e8752d44 29 #include "py/runtime.h"
pythontech 0:5868e8752d44 30 #include "py/repl.h"
pythontech 0:5868e8752d44 31
pythontech 0:5868e8752d44 32 #if MICROPY_HELPER_REPL
pythontech 0:5868e8752d44 33
pythontech 0:5868e8752d44 34 STATIC bool str_startswith_word(const char *str, const char *head) {
pythontech 0:5868e8752d44 35 mp_uint_t i;
pythontech 0:5868e8752d44 36 for (i = 0; str[i] && head[i]; i++) {
pythontech 0:5868e8752d44 37 if (str[i] != head[i]) {
pythontech 0:5868e8752d44 38 return false;
pythontech 0:5868e8752d44 39 }
pythontech 0:5868e8752d44 40 }
pythontech 0:5868e8752d44 41 return head[i] == '\0' && (str[i] == '\0' || !unichar_isident(str[i]));
pythontech 0:5868e8752d44 42 }
pythontech 0:5868e8752d44 43
pythontech 0:5868e8752d44 44 bool mp_repl_continue_with_input(const char *input) {
pythontech 0:5868e8752d44 45 // check for blank input
pythontech 0:5868e8752d44 46 if (input[0] == '\0') {
pythontech 0:5868e8752d44 47 return false;
pythontech 0:5868e8752d44 48 }
pythontech 0:5868e8752d44 49
pythontech 0:5868e8752d44 50 // check if input starts with a certain keyword
pythontech 0:5868e8752d44 51 bool starts_with_compound_keyword =
pythontech 0:5868e8752d44 52 input[0] == '@'
pythontech 0:5868e8752d44 53 || str_startswith_word(input, "if")
pythontech 0:5868e8752d44 54 || str_startswith_word(input, "while")
pythontech 0:5868e8752d44 55 || str_startswith_word(input, "for")
pythontech 0:5868e8752d44 56 || str_startswith_word(input, "try")
pythontech 0:5868e8752d44 57 || str_startswith_word(input, "with")
pythontech 0:5868e8752d44 58 || str_startswith_word(input, "def")
pythontech 0:5868e8752d44 59 || str_startswith_word(input, "class")
pythontech 0:5868e8752d44 60 ;
pythontech 0:5868e8752d44 61
pythontech 0:5868e8752d44 62 // check for unmatched open bracket, quote or escape quote
pythontech 0:5868e8752d44 63 #define Q_NONE (0)
pythontech 0:5868e8752d44 64 #define Q_1_SINGLE (1)
pythontech 0:5868e8752d44 65 #define Q_1_DOUBLE (2)
pythontech 0:5868e8752d44 66 #define Q_3_SINGLE (3)
pythontech 0:5868e8752d44 67 #define Q_3_DOUBLE (4)
pythontech 0:5868e8752d44 68 int n_paren = 0;
pythontech 0:5868e8752d44 69 int n_brack = 0;
pythontech 0:5868e8752d44 70 int n_brace = 0;
pythontech 0:5868e8752d44 71 int in_quote = Q_NONE;
pythontech 0:5868e8752d44 72 const char *i;
pythontech 0:5868e8752d44 73 for (i = input; *i; i++) {
pythontech 0:5868e8752d44 74 if (*i == '\'') {
pythontech 0:5868e8752d44 75 if ((in_quote == Q_NONE || in_quote == Q_3_SINGLE) && i[1] == '\'' && i[2] == '\'') {
pythontech 0:5868e8752d44 76 i += 2;
pythontech 0:5868e8752d44 77 in_quote = Q_3_SINGLE - in_quote;
pythontech 0:5868e8752d44 78 } else if (in_quote == Q_NONE || in_quote == Q_1_SINGLE) {
pythontech 0:5868e8752d44 79 in_quote = Q_1_SINGLE - in_quote;
pythontech 0:5868e8752d44 80 }
pythontech 0:5868e8752d44 81 } else if (*i == '"') {
pythontech 0:5868e8752d44 82 if ((in_quote == Q_NONE || in_quote == Q_3_DOUBLE) && i[1] == '"' && i[2] == '"') {
pythontech 0:5868e8752d44 83 i += 2;
pythontech 0:5868e8752d44 84 in_quote = Q_3_DOUBLE - in_quote;
pythontech 0:5868e8752d44 85 } else if (in_quote == Q_NONE || in_quote == Q_1_DOUBLE) {
pythontech 0:5868e8752d44 86 in_quote = Q_1_DOUBLE - in_quote;
pythontech 0:5868e8752d44 87 }
pythontech 0:5868e8752d44 88 } else if (*i == '\\' && (i[1] == '\'' || i[1] == '"')) {
pythontech 0:5868e8752d44 89 if (in_quote != Q_NONE) {
pythontech 0:5868e8752d44 90 i++;
pythontech 0:5868e8752d44 91 }
pythontech 0:5868e8752d44 92 } else if (in_quote == Q_NONE) {
pythontech 0:5868e8752d44 93 switch (*i) {
pythontech 0:5868e8752d44 94 case '(': n_paren += 1; break;
pythontech 0:5868e8752d44 95 case ')': n_paren -= 1; break;
pythontech 0:5868e8752d44 96 case '[': n_brack += 1; break;
pythontech 0:5868e8752d44 97 case ']': n_brack -= 1; break;
pythontech 0:5868e8752d44 98 case '{': n_brace += 1; break;
pythontech 0:5868e8752d44 99 case '}': n_brace -= 1; break;
pythontech 0:5868e8752d44 100 default: break;
pythontech 0:5868e8752d44 101 }
pythontech 0:5868e8752d44 102 }
pythontech 0:5868e8752d44 103 }
pythontech 0:5868e8752d44 104
pythontech 0:5868e8752d44 105 // continue if unmatched brackets or quotes
pythontech 0:5868e8752d44 106 if (n_paren > 0 || n_brack > 0 || n_brace > 0 || in_quote == Q_3_SINGLE || in_quote == Q_3_DOUBLE) {
pythontech 0:5868e8752d44 107 return true;
pythontech 0:5868e8752d44 108 }
pythontech 0:5868e8752d44 109
pythontech 0:5868e8752d44 110 // continue if last character was backslash (for line continuation)
pythontech 0:5868e8752d44 111 if (i[-1] == '\\') {
pythontech 0:5868e8752d44 112 return true;
pythontech 0:5868e8752d44 113 }
pythontech 0:5868e8752d44 114
pythontech 0:5868e8752d44 115 // continue if compound keyword and last line was not empty
pythontech 0:5868e8752d44 116 if (starts_with_compound_keyword && i[-1] != '\n') {
pythontech 0:5868e8752d44 117 return true;
pythontech 0:5868e8752d44 118 }
pythontech 0:5868e8752d44 119
pythontech 0:5868e8752d44 120 // otherwise, don't continue
pythontech 0:5868e8752d44 121 return false;
pythontech 0:5868e8752d44 122 }
pythontech 0:5868e8752d44 123
pythontech 0:5868e8752d44 124 mp_uint_t mp_repl_autocomplete(const char *str, mp_uint_t len, const mp_print_t *print, const char **compl_str) {
pythontech 0:5868e8752d44 125 // scan backwards to find start of "a.b.c" chain
pythontech 0:5868e8752d44 126 const char *top = str + len;
pythontech 0:5868e8752d44 127 for (const char *s = top; --s >= str;) {
pythontech 0:5868e8752d44 128 if (!(unichar_isalpha(*s) || unichar_isdigit(*s) || *s == '_' || *s == '.')) {
pythontech 0:5868e8752d44 129 ++s;
pythontech 0:5868e8752d44 130 str = s;
pythontech 0:5868e8752d44 131 break;
pythontech 0:5868e8752d44 132 }
pythontech 0:5868e8752d44 133 }
pythontech 0:5868e8752d44 134
pythontech 0:5868e8752d44 135 // begin search in locals dict
pythontech 0:5868e8752d44 136 mp_obj_dict_t *dict = mp_locals_get();
pythontech 0:5868e8752d44 137
pythontech 0:5868e8752d44 138 for (;;) {
pythontech 0:5868e8752d44 139 // get next word in string to complete
pythontech 0:5868e8752d44 140 const char *s_start = str;
pythontech 0:5868e8752d44 141 while (str < top && *str != '.') {
pythontech 0:5868e8752d44 142 ++str;
pythontech 0:5868e8752d44 143 }
pythontech 0:5868e8752d44 144 mp_uint_t s_len = str - s_start;
pythontech 0:5868e8752d44 145
pythontech 0:5868e8752d44 146 if (str < top) {
pythontech 0:5868e8752d44 147 // a complete word, lookup in current dict
pythontech 0:5868e8752d44 148
pythontech 0:5868e8752d44 149 mp_obj_t obj = MP_OBJ_NULL;
pythontech 0:5868e8752d44 150 for (mp_uint_t i = 0; i < dict->map.alloc; i++) {
pythontech 0:5868e8752d44 151 if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
pythontech 0:5868e8752d44 152 mp_uint_t d_len;
pythontech 0:5868e8752d44 153 const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);
pythontech 0:5868e8752d44 154 if (s_len == d_len && strncmp(s_start, d_str, d_len) == 0) {
pythontech 0:5868e8752d44 155 obj = dict->map.table[i].value;
pythontech 0:5868e8752d44 156 break;
pythontech 0:5868e8752d44 157 }
pythontech 0:5868e8752d44 158 }
pythontech 0:5868e8752d44 159 }
pythontech 0:5868e8752d44 160
pythontech 0:5868e8752d44 161 if (obj == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 162 // lookup failed
pythontech 0:5868e8752d44 163 return 0;
pythontech 0:5868e8752d44 164 }
pythontech 0:5868e8752d44 165
pythontech 0:5868e8752d44 166 // found an object of this name; try to get its dict
pythontech 0:5868e8752d44 167 if (MP_OBJ_IS_TYPE(obj, &mp_type_module)) {
pythontech 0:5868e8752d44 168 dict = mp_obj_module_get_globals(obj);
pythontech 0:5868e8752d44 169 } else {
pythontech 0:5868e8752d44 170 mp_obj_type_t *type;
pythontech 0:5868e8752d44 171 if (MP_OBJ_IS_TYPE(obj, &mp_type_type)) {
pythontech 0:5868e8752d44 172 type = MP_OBJ_TO_PTR(obj);
pythontech 0:5868e8752d44 173 } else {
pythontech 0:5868e8752d44 174 type = mp_obj_get_type(obj);
pythontech 0:5868e8752d44 175 }
pythontech 0:5868e8752d44 176 if (type->locals_dict != NULL && type->locals_dict->base.type == &mp_type_dict) {
pythontech 0:5868e8752d44 177 dict = type->locals_dict;
pythontech 0:5868e8752d44 178 } else {
pythontech 0:5868e8752d44 179 // obj has no dict
pythontech 0:5868e8752d44 180 return 0;
pythontech 0:5868e8752d44 181 }
pythontech 0:5868e8752d44 182 }
pythontech 0:5868e8752d44 183
pythontech 0:5868e8752d44 184 // skip '.' to move to next word
pythontech 0:5868e8752d44 185 ++str;
pythontech 0:5868e8752d44 186
pythontech 0:5868e8752d44 187 } else {
pythontech 0:5868e8752d44 188 // end of string, do completion on this partial name
pythontech 0:5868e8752d44 189
pythontech 0:5868e8752d44 190 // look for matches
pythontech 0:5868e8752d44 191 int n_found = 0;
pythontech 0:5868e8752d44 192 const char *match_str = NULL;
pythontech 0:5868e8752d44 193 mp_uint_t match_len = 0;
pythontech 0:5868e8752d44 194 for (mp_uint_t i = 0; i < dict->map.alloc; i++) {
pythontech 0:5868e8752d44 195 if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
pythontech 0:5868e8752d44 196 mp_uint_t d_len;
pythontech 0:5868e8752d44 197 const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);
pythontech 0:5868e8752d44 198 if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) {
pythontech 0:5868e8752d44 199 if (match_str == NULL) {
pythontech 0:5868e8752d44 200 match_str = d_str;
pythontech 0:5868e8752d44 201 match_len = d_len;
pythontech 0:5868e8752d44 202 } else {
pythontech 0:5868e8752d44 203 // search for longest common prefix of match_str and d_str
pythontech 0:5868e8752d44 204 // (assumes these strings are null-terminated)
pythontech 0:5868e8752d44 205 for (mp_uint_t j = s_len; j <= match_len && j <= d_len; ++j) {
pythontech 0:5868e8752d44 206 if (match_str[j] != d_str[j]) {
pythontech 0:5868e8752d44 207 match_len = j;
pythontech 0:5868e8752d44 208 break;
pythontech 0:5868e8752d44 209 }
pythontech 0:5868e8752d44 210 }
pythontech 0:5868e8752d44 211 }
pythontech 0:5868e8752d44 212 ++n_found;
pythontech 0:5868e8752d44 213 }
pythontech 0:5868e8752d44 214 }
pythontech 0:5868e8752d44 215 }
pythontech 0:5868e8752d44 216
pythontech 0:5868e8752d44 217 // nothing found
pythontech 0:5868e8752d44 218 if (n_found == 0) {
pythontech 0:5868e8752d44 219 return 0;
pythontech 0:5868e8752d44 220 }
pythontech 0:5868e8752d44 221
pythontech 0:5868e8752d44 222 // 1 match found, or multiple matches with a common prefix
pythontech 0:5868e8752d44 223 if (n_found == 1 || match_len > s_len) {
pythontech 0:5868e8752d44 224 *compl_str = match_str + s_len;
pythontech 0:5868e8752d44 225 return match_len - s_len;
pythontech 0:5868e8752d44 226 }
pythontech 0:5868e8752d44 227
pythontech 0:5868e8752d44 228 // multiple matches found, print them out
pythontech 0:5868e8752d44 229
pythontech 0:5868e8752d44 230 #define WORD_SLOT_LEN (16)
pythontech 0:5868e8752d44 231 #define MAX_LINE_LEN (4 * WORD_SLOT_LEN)
pythontech 0:5868e8752d44 232
pythontech 0:5868e8752d44 233 int line_len = MAX_LINE_LEN; // force a newline for first word
pythontech 0:5868e8752d44 234 for (mp_uint_t i = 0; i < dict->map.alloc; i++) {
pythontech 0:5868e8752d44 235 if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
pythontech 0:5868e8752d44 236 mp_uint_t d_len;
pythontech 0:5868e8752d44 237 const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);
pythontech 0:5868e8752d44 238 if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) {
pythontech 0:5868e8752d44 239 int gap = (line_len + WORD_SLOT_LEN - 1) / WORD_SLOT_LEN * WORD_SLOT_LEN - line_len;
pythontech 0:5868e8752d44 240 if (gap < 2) {
pythontech 0:5868e8752d44 241 gap += WORD_SLOT_LEN;
pythontech 0:5868e8752d44 242 }
pythontech 0:5868e8752d44 243 if (line_len + gap + d_len <= MAX_LINE_LEN) {
pythontech 0:5868e8752d44 244 // TODO optimise printing of gap?
pythontech 0:5868e8752d44 245 for (int j = 0; j < gap; ++j) {
pythontech 0:5868e8752d44 246 mp_print_str(print, " ");
pythontech 0:5868e8752d44 247 }
pythontech 0:5868e8752d44 248 mp_print_str(print, d_str);
pythontech 0:5868e8752d44 249 line_len += gap + d_len;
pythontech 0:5868e8752d44 250 } else {
pythontech 0:5868e8752d44 251 mp_printf(print, "\n%s", d_str);
pythontech 0:5868e8752d44 252 line_len = d_len;
pythontech 0:5868e8752d44 253 }
pythontech 0:5868e8752d44 254 }
pythontech 0:5868e8752d44 255 }
pythontech 0:5868e8752d44 256 }
pythontech 0:5868e8752d44 257 mp_print_str(print, "\n");
pythontech 0:5868e8752d44 258
pythontech 0:5868e8752d44 259 return (mp_uint_t)(-1); // indicate many matches
pythontech 0:5868e8752d44 260 }
pythontech 0:5868e8752d44 261 }
pythontech 0:5868e8752d44 262 }
pythontech 0:5868e8752d44 263
pythontech 0:5868e8752d44 264 #endif // MICROPY_HELPER_REPL