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 <stdbool.h>
pythontech 0:5868e8752d44 28 #include <stdlib.h>
pythontech 0:5868e8752d44 29
pythontech 0:5868e8752d44 30 #include "py/nlr.h"
pythontech 0:5868e8752d44 31 #include "py/parsenumbase.h"
pythontech 0:5868e8752d44 32 #include "py/parsenum.h"
pythontech 0:5868e8752d44 33 #include "py/smallint.h"
pythontech 0:5868e8752d44 34
pythontech 0:5868e8752d44 35 #if MICROPY_PY_BUILTINS_FLOAT
pythontech 0:5868e8752d44 36 #include <math.h>
pythontech 0:5868e8752d44 37 #endif
pythontech 0:5868e8752d44 38
pythontech 0:5868e8752d44 39 STATIC NORETURN void raise_exc(mp_obj_t exc, mp_lexer_t *lex) {
pythontech 0:5868e8752d44 40 // if lex!=NULL then the parser called us and we need to convert the
pythontech 0:5868e8752d44 41 // exception's type from ValueError to SyntaxError and add traceback info
pythontech 0:5868e8752d44 42 if (lex != NULL) {
pythontech 0:5868e8752d44 43 ((mp_obj_base_t*)MP_OBJ_TO_PTR(exc))->type = &mp_type_SyntaxError;
pythontech 0:5868e8752d44 44 mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL);
pythontech 0:5868e8752d44 45 }
pythontech 0:5868e8752d44 46 nlr_raise(exc);
pythontech 0:5868e8752d44 47 }
pythontech 0:5868e8752d44 48
pythontech 0:5868e8752d44 49 mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, mp_lexer_t *lex) {
pythontech 0:5868e8752d44 50 const byte *restrict str = (const byte *)str_;
pythontech 0:5868e8752d44 51 const byte *restrict top = str + len;
pythontech 0:5868e8752d44 52 bool neg = false;
pythontech 0:5868e8752d44 53 mp_obj_t ret_val;
pythontech 0:5868e8752d44 54
pythontech 0:5868e8752d44 55 // check radix base
pythontech 0:5868e8752d44 56 if ((base != 0 && base < 2) || base > 36) {
pythontech 0:5868e8752d44 57 // this won't be reached if lex!=NULL
pythontech 0:5868e8752d44 58 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "int() arg 2 must be >= 2 and <= 36"));
pythontech 0:5868e8752d44 59 }
pythontech 0:5868e8752d44 60
pythontech 0:5868e8752d44 61 // skip leading space
pythontech 0:5868e8752d44 62 for (; str < top && unichar_isspace(*str); str++) {
pythontech 0:5868e8752d44 63 }
pythontech 0:5868e8752d44 64
pythontech 0:5868e8752d44 65 // parse optional sign
pythontech 0:5868e8752d44 66 if (str < top) {
pythontech 0:5868e8752d44 67 if (*str == '+') {
pythontech 0:5868e8752d44 68 str++;
pythontech 0:5868e8752d44 69 } else if (*str == '-') {
pythontech 0:5868e8752d44 70 str++;
pythontech 0:5868e8752d44 71 neg = true;
pythontech 0:5868e8752d44 72 }
pythontech 0:5868e8752d44 73 }
pythontech 0:5868e8752d44 74
pythontech 0:5868e8752d44 75 // parse optional base prefix
pythontech 0:5868e8752d44 76 str += mp_parse_num_base((const char*)str, top - str, &base);
pythontech 0:5868e8752d44 77
pythontech 0:5868e8752d44 78 // string should be an integer number
pythontech 0:5868e8752d44 79 mp_int_t int_val = 0;
pythontech 0:5868e8752d44 80 const byte *restrict str_val_start = str;
pythontech 0:5868e8752d44 81 for (; str < top; str++) {
pythontech 0:5868e8752d44 82 // get next digit as a value
pythontech 0:5868e8752d44 83 mp_uint_t dig = *str;
pythontech 0:5868e8752d44 84 if (unichar_isdigit(dig) && (int)dig - '0' < base) {
pythontech 0:5868e8752d44 85 // 0-9 digit
pythontech 0:5868e8752d44 86 dig = dig - '0';
pythontech 0:5868e8752d44 87 } else if (base == 16) {
pythontech 0:5868e8752d44 88 dig |= 0x20;
pythontech 0:5868e8752d44 89 if ('a' <= dig && dig <= 'f') {
pythontech 0:5868e8752d44 90 // a-f hex digit
pythontech 0:5868e8752d44 91 dig = dig - 'a' + 10;
pythontech 0:5868e8752d44 92 } else {
pythontech 0:5868e8752d44 93 // unknown character
pythontech 0:5868e8752d44 94 break;
pythontech 0:5868e8752d44 95 }
pythontech 0:5868e8752d44 96 } else {
pythontech 0:5868e8752d44 97 // unknown character
pythontech 0:5868e8752d44 98 break;
pythontech 0:5868e8752d44 99 }
pythontech 0:5868e8752d44 100
pythontech 0:5868e8752d44 101 // add next digi and check for overflow
pythontech 0:5868e8752d44 102 if (mp_small_int_mul_overflow(int_val, base)) {
pythontech 0:5868e8752d44 103 goto overflow;
pythontech 0:5868e8752d44 104 }
pythontech 0:5868e8752d44 105 int_val = int_val * base + dig;
pythontech 0:5868e8752d44 106 if (!MP_SMALL_INT_FITS(int_val)) {
pythontech 0:5868e8752d44 107 goto overflow;
pythontech 0:5868e8752d44 108 }
pythontech 0:5868e8752d44 109 }
pythontech 0:5868e8752d44 110
pythontech 0:5868e8752d44 111 // negate value if needed
pythontech 0:5868e8752d44 112 if (neg) {
pythontech 0:5868e8752d44 113 int_val = -int_val;
pythontech 0:5868e8752d44 114 }
pythontech 0:5868e8752d44 115
pythontech 0:5868e8752d44 116 // create the small int
pythontech 0:5868e8752d44 117 ret_val = MP_OBJ_NEW_SMALL_INT(int_val);
pythontech 0:5868e8752d44 118
pythontech 0:5868e8752d44 119 have_ret_val:
pythontech 0:5868e8752d44 120 // check we parsed something
pythontech 0:5868e8752d44 121 if (str == str_val_start) {
pythontech 0:5868e8752d44 122 goto value_error;
pythontech 0:5868e8752d44 123 }
pythontech 0:5868e8752d44 124
pythontech 0:5868e8752d44 125 // skip trailing space
pythontech 0:5868e8752d44 126 for (; str < top && unichar_isspace(*str); str++) {
pythontech 0:5868e8752d44 127 }
pythontech 0:5868e8752d44 128
pythontech 0:5868e8752d44 129 // check we reached the end of the string
pythontech 0:5868e8752d44 130 if (str != top) {
pythontech 0:5868e8752d44 131 goto value_error;
pythontech 0:5868e8752d44 132 }
pythontech 0:5868e8752d44 133
pythontech 0:5868e8752d44 134 // return the object
pythontech 0:5868e8752d44 135 return ret_val;
pythontech 0:5868e8752d44 136
pythontech 0:5868e8752d44 137 overflow:
pythontech 0:5868e8752d44 138 // reparse using long int
pythontech 0:5868e8752d44 139 {
pythontech 0:5868e8752d44 140 const char *s2 = (const char*)str_val_start;
pythontech 0:5868e8752d44 141 ret_val = mp_obj_new_int_from_str_len(&s2, top - str_val_start, neg, base);
pythontech 0:5868e8752d44 142 str = (const byte*)s2;
pythontech 0:5868e8752d44 143 goto have_ret_val;
pythontech 0:5868e8752d44 144 }
pythontech 0:5868e8752d44 145
pythontech 0:5868e8752d44 146 value_error:
pythontech 0:5868e8752d44 147 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
pythontech 0:5868e8752d44 148 mp_obj_t exc = mp_obj_new_exception_msg(&mp_type_ValueError,
pythontech 0:5868e8752d44 149 "invalid syntax for integer");
pythontech 0:5868e8752d44 150 raise_exc(exc, lex);
pythontech 0:5868e8752d44 151 } else if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL) {
pythontech 0:5868e8752d44 152 mp_obj_t exc = mp_obj_new_exception_msg_varg(&mp_type_ValueError,
pythontech 0:5868e8752d44 153 "invalid syntax for integer with base %d", base);
pythontech 0:5868e8752d44 154 raise_exc(exc, lex);
pythontech 0:5868e8752d44 155 } else {
pythontech 0:5868e8752d44 156 vstr_t vstr;
pythontech 0:5868e8752d44 157 mp_print_t print;
pythontech 0:5868e8752d44 158 vstr_init_print(&vstr, 50, &print);
pythontech 0:5868e8752d44 159 mp_printf(&print, "invalid syntax for integer with base %d: ", base);
pythontech 0:5868e8752d44 160 mp_str_print_quoted(&print, str_val_start, top - str_val_start, true);
pythontech 0:5868e8752d44 161 mp_obj_t exc = mp_obj_new_exception_arg1(&mp_type_ValueError,
pythontech 0:5868e8752d44 162 mp_obj_new_str_from_vstr(&mp_type_str, &vstr));
pythontech 0:5868e8752d44 163 raise_exc(exc, lex);
pythontech 0:5868e8752d44 164 }
pythontech 0:5868e8752d44 165 }
pythontech 0:5868e8752d44 166
pythontech 0:5868e8752d44 167 typedef enum {
pythontech 0:5868e8752d44 168 PARSE_DEC_IN_INTG,
pythontech 0:5868e8752d44 169 PARSE_DEC_IN_FRAC,
pythontech 0:5868e8752d44 170 PARSE_DEC_IN_EXP,
pythontech 0:5868e8752d44 171 } parse_dec_in_t;
pythontech 0:5868e8752d44 172
pythontech 0:5868e8752d44 173 mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex) {
pythontech 0:5868e8752d44 174 #if MICROPY_PY_BUILTINS_FLOAT
pythontech 0:5868e8752d44 175 const char *top = str + len;
pythontech 0:5868e8752d44 176 mp_float_t dec_val = 0;
pythontech 0:5868e8752d44 177 bool dec_neg = false;
pythontech 0:5868e8752d44 178 bool imag = false;
pythontech 0:5868e8752d44 179
pythontech 0:5868e8752d44 180 // skip leading space
pythontech 0:5868e8752d44 181 for (; str < top && unichar_isspace(*str); str++) {
pythontech 0:5868e8752d44 182 }
pythontech 0:5868e8752d44 183
pythontech 0:5868e8752d44 184 // parse optional sign
pythontech 0:5868e8752d44 185 if (str < top) {
pythontech 0:5868e8752d44 186 if (*str == '+') {
pythontech 0:5868e8752d44 187 str++;
pythontech 0:5868e8752d44 188 } else if (*str == '-') {
pythontech 0:5868e8752d44 189 str++;
pythontech 0:5868e8752d44 190 dec_neg = true;
pythontech 0:5868e8752d44 191 }
pythontech 0:5868e8752d44 192 }
pythontech 0:5868e8752d44 193
pythontech 0:5868e8752d44 194 const char *str_val_start = str;
pythontech 0:5868e8752d44 195
pythontech 0:5868e8752d44 196 // determine what the string is
pythontech 0:5868e8752d44 197 if (str < top && (str[0] | 0x20) == 'i') {
pythontech 0:5868e8752d44 198 // string starts with 'i', should be 'inf' or 'infinity' (case insensitive)
pythontech 0:5868e8752d44 199 if (str + 2 < top && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'f') {
pythontech 0:5868e8752d44 200 // inf
pythontech 0:5868e8752d44 201 str += 3;
pythontech 0:5868e8752d44 202 dec_val = INFINITY;
pythontech 0:5868e8752d44 203 if (str + 4 < top && (str[0] | 0x20) == 'i' && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'i' && (str[3] | 0x20) == 't' && (str[4] | 0x20) == 'y') {
pythontech 0:5868e8752d44 204 // infinity
pythontech 0:5868e8752d44 205 str += 5;
pythontech 0:5868e8752d44 206 }
pythontech 0:5868e8752d44 207 }
pythontech 0:5868e8752d44 208 } else if (str < top && (str[0] | 0x20) == 'n') {
pythontech 0:5868e8752d44 209 // string starts with 'n', should be 'nan' (case insensitive)
pythontech 0:5868e8752d44 210 if (str + 2 < top && (str[1] | 0x20) == 'a' && (str[2] | 0x20) == 'n') {
pythontech 0:5868e8752d44 211 // NaN
pythontech 0:5868e8752d44 212 str += 3;
pythontech 0:5868e8752d44 213 dec_val = MICROPY_FLOAT_C_FUN(nan)("");
pythontech 0:5868e8752d44 214 }
pythontech 0:5868e8752d44 215 } else {
pythontech 0:5868e8752d44 216 // string should be a decimal number
pythontech 0:5868e8752d44 217 parse_dec_in_t in = PARSE_DEC_IN_INTG;
pythontech 0:5868e8752d44 218 bool exp_neg = false;
pythontech 0:5868e8752d44 219 mp_float_t frac_mult = 0.1;
pythontech 0:5868e8752d44 220 mp_int_t exp_val = 0;
pythontech 0:5868e8752d44 221 while (str < top) {
pythontech 0:5868e8752d44 222 mp_uint_t dig = *str++;
pythontech 0:5868e8752d44 223 if ('0' <= dig && dig <= '9') {
pythontech 0:5868e8752d44 224 dig -= '0';
pythontech 0:5868e8752d44 225 if (in == PARSE_DEC_IN_EXP) {
pythontech 0:5868e8752d44 226 exp_val = 10 * exp_val + dig;
pythontech 0:5868e8752d44 227 } else {
pythontech 0:5868e8752d44 228 if (in == PARSE_DEC_IN_FRAC) {
pythontech 0:5868e8752d44 229 dec_val += dig * frac_mult;
pythontech 0:5868e8752d44 230 frac_mult *= 0.1;
pythontech 0:5868e8752d44 231 } else {
pythontech 0:5868e8752d44 232 dec_val = 10 * dec_val + dig;
pythontech 0:5868e8752d44 233 }
pythontech 0:5868e8752d44 234 }
pythontech 0:5868e8752d44 235 } else if (in == PARSE_DEC_IN_INTG && dig == '.') {
pythontech 0:5868e8752d44 236 in = PARSE_DEC_IN_FRAC;
pythontech 0:5868e8752d44 237 } else if (in != PARSE_DEC_IN_EXP && ((dig | 0x20) == 'e')) {
pythontech 0:5868e8752d44 238 in = PARSE_DEC_IN_EXP;
pythontech 0:5868e8752d44 239 if (str < top) {
pythontech 0:5868e8752d44 240 if (str[0] == '+') {
pythontech 0:5868e8752d44 241 str++;
pythontech 0:5868e8752d44 242 } else if (str[0] == '-') {
pythontech 0:5868e8752d44 243 str++;
pythontech 0:5868e8752d44 244 exp_neg = true;
pythontech 0:5868e8752d44 245 }
pythontech 0:5868e8752d44 246 }
pythontech 0:5868e8752d44 247 if (str == top) {
pythontech 0:5868e8752d44 248 goto value_error;
pythontech 0:5868e8752d44 249 }
pythontech 0:5868e8752d44 250 } else if (allow_imag && (dig | 0x20) == 'j') {
pythontech 0:5868e8752d44 251 imag = true;
pythontech 0:5868e8752d44 252 break;
pythontech 0:5868e8752d44 253 } else {
pythontech 0:5868e8752d44 254 // unknown character
pythontech 0:5868e8752d44 255 str--;
pythontech 0:5868e8752d44 256 break;
pythontech 0:5868e8752d44 257 }
pythontech 0:5868e8752d44 258 }
pythontech 0:5868e8752d44 259
pythontech 0:5868e8752d44 260 // work out the exponent
pythontech 0:5868e8752d44 261 if (exp_neg) {
pythontech 0:5868e8752d44 262 exp_val = -exp_val;
pythontech 0:5868e8752d44 263 }
pythontech 0:5868e8752d44 264
pythontech 0:5868e8752d44 265 // apply the exponent
pythontech 0:5868e8752d44 266 dec_val *= MICROPY_FLOAT_C_FUN(pow)(10, exp_val);
pythontech 0:5868e8752d44 267 }
pythontech 0:5868e8752d44 268
pythontech 0:5868e8752d44 269 // negate value if needed
pythontech 0:5868e8752d44 270 if (dec_neg) {
pythontech 0:5868e8752d44 271 dec_val = -dec_val;
pythontech 0:5868e8752d44 272 }
pythontech 0:5868e8752d44 273
pythontech 0:5868e8752d44 274 // check we parsed something
pythontech 0:5868e8752d44 275 if (str == str_val_start) {
pythontech 0:5868e8752d44 276 goto value_error;
pythontech 0:5868e8752d44 277 }
pythontech 0:5868e8752d44 278
pythontech 0:5868e8752d44 279 // skip trailing space
pythontech 0:5868e8752d44 280 for (; str < top && unichar_isspace(*str); str++) {
pythontech 0:5868e8752d44 281 }
pythontech 0:5868e8752d44 282
pythontech 0:5868e8752d44 283 // check we reached the end of the string
pythontech 0:5868e8752d44 284 if (str != top) {
pythontech 0:5868e8752d44 285 goto value_error;
pythontech 0:5868e8752d44 286 }
pythontech 0:5868e8752d44 287
pythontech 0:5868e8752d44 288 // return the object
pythontech 0:5868e8752d44 289 #if MICROPY_PY_BUILTINS_COMPLEX
pythontech 0:5868e8752d44 290 if (imag) {
pythontech 0:5868e8752d44 291 return mp_obj_new_complex(0, dec_val);
pythontech 0:5868e8752d44 292 } else if (force_complex) {
pythontech 0:5868e8752d44 293 return mp_obj_new_complex(dec_val, 0);
pythontech 0:5868e8752d44 294 #else
pythontech 0:5868e8752d44 295 if (imag || force_complex) {
pythontech 0:5868e8752d44 296 raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, "complex values not supported"), lex);
pythontech 0:5868e8752d44 297 #endif
pythontech 0:5868e8752d44 298 } else {
pythontech 0:5868e8752d44 299 return mp_obj_new_float(dec_val);
pythontech 0:5868e8752d44 300 }
pythontech 0:5868e8752d44 301
pythontech 0:5868e8752d44 302 value_error:
pythontech 0:5868e8752d44 303 raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid syntax for number"), lex);
pythontech 0:5868e8752d44 304
pythontech 0:5868e8752d44 305 #else
pythontech 0:5868e8752d44 306 raise_exc(mp_obj_new_exception_msg(&mp_type_ValueError, "decimal numbers not supported"), lex);
pythontech 0:5868e8752d44 307 #endif
pythontech 0:5868e8752d44 308 }