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:
2:c89e95946844
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 // This code glues the code emitters to the runtime.
pythontech 0:5868e8752d44 28
pythontech 0:5868e8752d44 29 #include <stdint.h>
pythontech 0:5868e8752d44 30 #include <stdio.h>
pythontech 0:5868e8752d44 31 #include <string.h>
pythontech 0:5868e8752d44 32 #include <assert.h>
pythontech 0:5868e8752d44 33
pythontech 0:5868e8752d44 34 #include "py/emitglue.h"
pythontech 0:5868e8752d44 35 #include "py/runtime0.h"
pythontech 0:5868e8752d44 36 #include "py/bc.h"
pythontech 0:5868e8752d44 37
pythontech 0:5868e8752d44 38 #if 0 // print debugging info
pythontech 0:5868e8752d44 39 #define DEBUG_PRINT (1)
pythontech 0:5868e8752d44 40 #define WRITE_CODE (1)
pythontech 0:5868e8752d44 41 #define DEBUG_printf DEBUG_printf
pythontech 0:5868e8752d44 42 #define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__)
pythontech 0:5868e8752d44 43 #else // don't print debugging info
pythontech 0:5868e8752d44 44 #define DEBUG_printf(...) (void)0
pythontech 0:5868e8752d44 45 #define DEBUG_OP_printf(...) (void)0
pythontech 0:5868e8752d44 46 #endif
pythontech 0:5868e8752d44 47
pythontech 0:5868e8752d44 48 #if MICROPY_DEBUG_PRINTERS
pythontech 0:5868e8752d44 49 mp_uint_t mp_verbose_flag = 0;
pythontech 0:5868e8752d44 50 #endif
pythontech 0:5868e8752d44 51
pythontech 0:5868e8752d44 52 mp_raw_code_t *mp_emit_glue_new_raw_code(void) {
pythontech 0:5868e8752d44 53 mp_raw_code_t *rc = m_new0(mp_raw_code_t, 1);
pythontech 0:5868e8752d44 54 rc->kind = MP_CODE_RESERVED;
pythontech 0:5868e8752d44 55 return rc;
pythontech 0:5868e8752d44 56 }
pythontech 0:5868e8752d44 57
pythontech 0:5868e8752d44 58 void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, mp_uint_t len,
pythontech 0:5868e8752d44 59 const mp_uint_t *const_table,
pythontech 0:5868e8752d44 60 #if MICROPY_PERSISTENT_CODE_SAVE
pythontech 0:5868e8752d44 61 uint16_t n_obj, uint16_t n_raw_code,
pythontech 0:5868e8752d44 62 #endif
pythontech 0:5868e8752d44 63 mp_uint_t scope_flags) {
pythontech 0:5868e8752d44 64
pythontech 0:5868e8752d44 65 rc->kind = MP_CODE_BYTECODE;
pythontech 0:5868e8752d44 66 rc->scope_flags = scope_flags;
pythontech 0:5868e8752d44 67 rc->data.u_byte.bytecode = code;
pythontech 0:5868e8752d44 68 rc->data.u_byte.const_table = const_table;
pythontech 0:5868e8752d44 69 #if MICROPY_PERSISTENT_CODE_SAVE
pythontech 0:5868e8752d44 70 rc->data.u_byte.bc_len = len;
pythontech 0:5868e8752d44 71 rc->data.u_byte.n_obj = n_obj;
pythontech 0:5868e8752d44 72 rc->data.u_byte.n_raw_code = n_raw_code;
pythontech 0:5868e8752d44 73 #endif
pythontech 0:5868e8752d44 74
pythontech 0:5868e8752d44 75 #ifdef DEBUG_PRINT
pythontech 0:5868e8752d44 76 DEBUG_printf("assign byte code: code=%p len=" UINT_FMT " flags=%x\n", code, len, (uint)scope_flags);
pythontech 0:5868e8752d44 77 #endif
pythontech 0:5868e8752d44 78 #if MICROPY_DEBUG_PRINTERS
pythontech 0:5868e8752d44 79 if (mp_verbose_flag >= 2) {
pythontech 0:5868e8752d44 80 mp_bytecode_print(rc, code, len, const_table);
pythontech 0:5868e8752d44 81 }
pythontech 0:5868e8752d44 82 #endif
pythontech 0:5868e8752d44 83 }
pythontech 0:5868e8752d44 84
pythontech 0:5868e8752d44 85 #if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 86 void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, const mp_uint_t *const_table, mp_uint_t n_pos_args, mp_uint_t scope_flags, mp_uint_t type_sig) {
pythontech 0:5868e8752d44 87 assert(kind == MP_CODE_NATIVE_PY || kind == MP_CODE_NATIVE_VIPER || kind == MP_CODE_NATIVE_ASM);
pythontech 0:5868e8752d44 88 rc->kind = kind;
pythontech 0:5868e8752d44 89 rc->scope_flags = scope_flags;
pythontech 0:5868e8752d44 90 rc->n_pos_args = n_pos_args;
pythontech 0:5868e8752d44 91 rc->data.u_native.fun_data = fun_data;
pythontech 0:5868e8752d44 92 rc->data.u_native.const_table = const_table;
pythontech 0:5868e8752d44 93 rc->data.u_native.type_sig = type_sig;
pythontech 0:5868e8752d44 94
pythontech 0:5868e8752d44 95 #ifdef DEBUG_PRINT
pythontech 0:5868e8752d44 96 DEBUG_printf("assign native: kind=%d fun=%p len=" UINT_FMT " n_pos_args=" UINT_FMT " flags=%x\n", kind, fun_data, fun_len, n_pos_args, (uint)scope_flags);
pythontech 0:5868e8752d44 97 for (mp_uint_t i = 0; i < fun_len; i++) {
pythontech 0:5868e8752d44 98 if (i > 0 && i % 16 == 0) {
pythontech 0:5868e8752d44 99 DEBUG_printf("\n");
pythontech 0:5868e8752d44 100 }
pythontech 0:5868e8752d44 101 DEBUG_printf(" %02x", ((byte*)fun_data)[i]);
pythontech 0:5868e8752d44 102 }
pythontech 0:5868e8752d44 103 DEBUG_printf("\n");
pythontech 0:5868e8752d44 104
pythontech 0:5868e8752d44 105 #ifdef WRITE_CODE
pythontech 0:5868e8752d44 106 FILE *fp_write_code = fopen("out-code", "wb");
pythontech 0:5868e8752d44 107 fwrite(fun_data, fun_len, 1, fp_write_code);
pythontech 0:5868e8752d44 108 fclose(fp_write_code);
pythontech 0:5868e8752d44 109 #endif
pythontech 0:5868e8752d44 110 #else
pythontech 0:5868e8752d44 111 (void)fun_len;
pythontech 0:5868e8752d44 112 #endif
pythontech 0:5868e8752d44 113 }
pythontech 0:5868e8752d44 114 #endif
pythontech 0:5868e8752d44 115
Colin Hogben 2:c89e95946844 116 mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args) {
pythontech 0:5868e8752d44 117 DEBUG_OP_printf("make_function_from_raw_code %p\n", rc);
pythontech 0:5868e8752d44 118 assert(rc != NULL);
pythontech 0:5868e8752d44 119
pythontech 0:5868e8752d44 120 // def_args must be MP_OBJ_NULL or a tuple
pythontech 0:5868e8752d44 121 assert(def_args == MP_OBJ_NULL || MP_OBJ_IS_TYPE(def_args, &mp_type_tuple));
pythontech 0:5868e8752d44 122
pythontech 0:5868e8752d44 123 // def_kw_args must be MP_OBJ_NULL or a dict
pythontech 0:5868e8752d44 124 assert(def_kw_args == MP_OBJ_NULL || MP_OBJ_IS_TYPE(def_kw_args, &mp_type_dict));
pythontech 0:5868e8752d44 125
pythontech 0:5868e8752d44 126 // make the function, depending on the raw code kind
pythontech 0:5868e8752d44 127 mp_obj_t fun;
pythontech 0:5868e8752d44 128 switch (rc->kind) {
pythontech 0:5868e8752d44 129 case MP_CODE_BYTECODE:
pythontech 0:5868e8752d44 130 no_other_choice:
pythontech 0:5868e8752d44 131 fun = mp_obj_new_fun_bc(def_args, def_kw_args, rc->data.u_byte.bytecode, rc->data.u_byte.const_table);
pythontech 0:5868e8752d44 132 break;
pythontech 0:5868e8752d44 133 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 134 case MP_CODE_NATIVE_PY:
pythontech 0:5868e8752d44 135 fun = mp_obj_new_fun_native(def_args, def_kw_args, rc->data.u_native.fun_data, rc->data.u_native.const_table);
pythontech 0:5868e8752d44 136 break;
pythontech 0:5868e8752d44 137 case MP_CODE_NATIVE_VIPER:
pythontech 0:5868e8752d44 138 fun = mp_obj_new_fun_viper(rc->n_pos_args, rc->data.u_native.fun_data, rc->data.u_native.type_sig);
pythontech 0:5868e8752d44 139 break;
pythontech 0:5868e8752d44 140 #endif
pythontech 0:5868e8752d44 141 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 142 case MP_CODE_NATIVE_ASM:
pythontech 0:5868e8752d44 143 fun = mp_obj_new_fun_asm(rc->n_pos_args, rc->data.u_native.fun_data, rc->data.u_native.type_sig);
pythontech 0:5868e8752d44 144 break;
pythontech 0:5868e8752d44 145 #endif
pythontech 0:5868e8752d44 146 default:
pythontech 0:5868e8752d44 147 // raw code was never set (this should not happen)
pythontech 0:5868e8752d44 148 assert(0);
pythontech 0:5868e8752d44 149 goto no_other_choice; // to help flow control analysis
pythontech 0:5868e8752d44 150 }
pythontech 0:5868e8752d44 151
pythontech 0:5868e8752d44 152 // check for generator functions and if so wrap in generator object
pythontech 0:5868e8752d44 153 if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) {
pythontech 0:5868e8752d44 154 fun = mp_obj_new_gen_wrap(fun);
pythontech 0:5868e8752d44 155 }
pythontech 0:5868e8752d44 156
pythontech 0:5868e8752d44 157 return fun;
pythontech 0:5868e8752d44 158 }
pythontech 0:5868e8752d44 159
Colin Hogben 2:c89e95946844 160 mp_obj_t mp_make_closure_from_raw_code(const mp_raw_code_t *rc, mp_uint_t n_closed_over, const mp_obj_t *args) {
pythontech 0:5868e8752d44 161 DEBUG_OP_printf("make_closure_from_raw_code %p " UINT_FMT " %p\n", rc, n_closed_over, args);
pythontech 0:5868e8752d44 162 // make function object
pythontech 0:5868e8752d44 163 mp_obj_t ffun;
pythontech 0:5868e8752d44 164 if (n_closed_over & 0x100) {
pythontech 0:5868e8752d44 165 // default positional and keyword args given
pythontech 0:5868e8752d44 166 ffun = mp_make_function_from_raw_code(rc, args[0], args[1]);
pythontech 0:5868e8752d44 167 } else {
pythontech 0:5868e8752d44 168 // default positional and keyword args not given
pythontech 0:5868e8752d44 169 ffun = mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL);
pythontech 0:5868e8752d44 170 }
pythontech 0:5868e8752d44 171 // wrap function in closure object
pythontech 0:5868e8752d44 172 return mp_obj_new_closure(ffun, n_closed_over & 0xff, args + ((n_closed_over >> 7) & 2));
pythontech 0:5868e8752d44 173 }
pythontech 0:5868e8752d44 174
Colin Hogben 2:c89e95946844 175 #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE
pythontech 0:5868e8752d44 176
pythontech 0:5868e8752d44 177 #include "py/smallint.h"
pythontech 0:5868e8752d44 178
pythontech 0:5868e8752d44 179 // The feature flags byte encodes the compile-time config options that
pythontech 0:5868e8752d44 180 // affect the generate bytecode.
pythontech 0:5868e8752d44 181 #define MPY_FEATURE_FLAGS ( \
pythontech 0:5868e8752d44 182 ((MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) << 0) \
pythontech 0:5868e8752d44 183 | ((MICROPY_PY_BUILTINS_STR_UNICODE) << 1) \
pythontech 0:5868e8752d44 184 )
pythontech 0:5868e8752d44 185 // This is a version of the flags that can be configured at runtime.
pythontech 0:5868e8752d44 186 #define MPY_FEATURE_FLAGS_DYNAMIC ( \
pythontech 0:5868e8752d44 187 ((MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE_DYNAMIC) << 0) \
pythontech 0:5868e8752d44 188 | ((MICROPY_PY_BUILTINS_STR_UNICODE_DYNAMIC) << 1) \
pythontech 0:5868e8752d44 189 )
pythontech 0:5868e8752d44 190
pythontech 0:5868e8752d44 191 #if MICROPY_PERSISTENT_CODE_LOAD || (MICROPY_PERSISTENT_CODE_SAVE && !MICROPY_DYNAMIC_COMPILER)
pythontech 0:5868e8752d44 192 // The bytecode will depend on the number of bits in a small-int, and
pythontech 0:5868e8752d44 193 // this function computes that (could make it a fixed constant, but it
pythontech 0:5868e8752d44 194 // would need to be defined in mpconfigport.h).
pythontech 0:5868e8752d44 195 STATIC int mp_small_int_bits(void) {
pythontech 0:5868e8752d44 196 mp_int_t i = MP_SMALL_INT_MAX;
pythontech 0:5868e8752d44 197 int n = 1;
pythontech 0:5868e8752d44 198 while (i != 0) {
pythontech 0:5868e8752d44 199 i >>= 1;
pythontech 0:5868e8752d44 200 ++n;
pythontech 0:5868e8752d44 201 }
pythontech 0:5868e8752d44 202 return n;
pythontech 0:5868e8752d44 203 }
pythontech 0:5868e8752d44 204 #endif
pythontech 0:5868e8752d44 205
pythontech 0:5868e8752d44 206 typedef struct _bytecode_prelude_t {
pythontech 0:5868e8752d44 207 uint n_state;
pythontech 0:5868e8752d44 208 uint n_exc_stack;
pythontech 0:5868e8752d44 209 uint scope_flags;
pythontech 0:5868e8752d44 210 uint n_pos_args;
pythontech 0:5868e8752d44 211 uint n_kwonly_args;
pythontech 0:5868e8752d44 212 uint n_def_pos_args;
pythontech 0:5868e8752d44 213 uint code_info_size;
pythontech 0:5868e8752d44 214 } bytecode_prelude_t;
pythontech 0:5868e8752d44 215
pythontech 0:5868e8752d44 216 // ip will point to start of opcodes
pythontech 0:5868e8752d44 217 // ip2 will point to simple_name, source_file qstrs
pythontech 0:5868e8752d44 218 STATIC void extract_prelude(const byte **ip, const byte **ip2, bytecode_prelude_t *prelude) {
pythontech 0:5868e8752d44 219 prelude->n_state = mp_decode_uint(ip);
pythontech 0:5868e8752d44 220 prelude->n_exc_stack = mp_decode_uint(ip);
pythontech 0:5868e8752d44 221 prelude->scope_flags = *(*ip)++;
pythontech 0:5868e8752d44 222 prelude->n_pos_args = *(*ip)++;
pythontech 0:5868e8752d44 223 prelude->n_kwonly_args = *(*ip)++;
pythontech 0:5868e8752d44 224 prelude->n_def_pos_args = *(*ip)++;
pythontech 0:5868e8752d44 225 *ip2 = *ip;
pythontech 0:5868e8752d44 226 prelude->code_info_size = mp_decode_uint(ip2);
pythontech 0:5868e8752d44 227 *ip += prelude->code_info_size;
pythontech 0:5868e8752d44 228 while (*(*ip)++ != 255) {
pythontech 0:5868e8752d44 229 }
pythontech 0:5868e8752d44 230 }
pythontech 0:5868e8752d44 231
Colin Hogben 2:c89e95946844 232 #endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE
pythontech 0:5868e8752d44 233
pythontech 0:5868e8752d44 234 #if MICROPY_PERSISTENT_CODE_LOAD
pythontech 0:5868e8752d44 235
pythontech 0:5868e8752d44 236 #include "py/parsenum.h"
pythontech 0:5868e8752d44 237 #include "py/bc0.h"
pythontech 0:5868e8752d44 238
pythontech 0:5868e8752d44 239 STATIC int read_byte(mp_reader_t *reader) {
pythontech 0:5868e8752d44 240 return reader->read_byte(reader->data);
pythontech 0:5868e8752d44 241 }
pythontech 0:5868e8752d44 242
pythontech 0:5868e8752d44 243 STATIC void read_bytes(mp_reader_t *reader, byte *buf, size_t len) {
pythontech 0:5868e8752d44 244 while (len-- > 0) {
pythontech 0:5868e8752d44 245 *buf++ = reader->read_byte(reader->data);
pythontech 0:5868e8752d44 246 }
pythontech 0:5868e8752d44 247 }
pythontech 0:5868e8752d44 248
pythontech 0:5868e8752d44 249 STATIC mp_uint_t read_uint(mp_reader_t *reader) {
pythontech 0:5868e8752d44 250 mp_uint_t unum = 0;
pythontech 0:5868e8752d44 251 for (;;) {
pythontech 0:5868e8752d44 252 byte b = reader->read_byte(reader->data);
pythontech 0:5868e8752d44 253 unum = (unum << 7) | (b & 0x7f);
pythontech 0:5868e8752d44 254 if ((b & 0x80) == 0) {
pythontech 0:5868e8752d44 255 break;
pythontech 0:5868e8752d44 256 }
pythontech 0:5868e8752d44 257 }
pythontech 0:5868e8752d44 258 return unum;
pythontech 0:5868e8752d44 259 }
pythontech 0:5868e8752d44 260
pythontech 0:5868e8752d44 261 STATIC qstr load_qstr(mp_reader_t *reader) {
pythontech 0:5868e8752d44 262 mp_uint_t len = read_uint(reader);
pythontech 0:5868e8752d44 263 char *str = m_new(char, len);
pythontech 0:5868e8752d44 264 read_bytes(reader, (byte*)str, len);
pythontech 0:5868e8752d44 265 qstr qst = qstr_from_strn(str, len);
pythontech 0:5868e8752d44 266 m_del(char, str, len);
pythontech 0:5868e8752d44 267 return qst;
pythontech 0:5868e8752d44 268 }
pythontech 0:5868e8752d44 269
pythontech 0:5868e8752d44 270 STATIC mp_obj_t load_obj(mp_reader_t *reader) {
pythontech 0:5868e8752d44 271 byte obj_type = read_byte(reader);
pythontech 0:5868e8752d44 272 if (obj_type == 'e') {
pythontech 0:5868e8752d44 273 return MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj);
pythontech 0:5868e8752d44 274 } else {
pythontech 0:5868e8752d44 275 size_t len = read_uint(reader);
pythontech 0:5868e8752d44 276 vstr_t vstr;
pythontech 0:5868e8752d44 277 vstr_init_len(&vstr, len);
pythontech 0:5868e8752d44 278 read_bytes(reader, (byte*)vstr.buf, len);
pythontech 0:5868e8752d44 279 if (obj_type == 's' || obj_type == 'b') {
pythontech 0:5868e8752d44 280 return mp_obj_new_str_from_vstr(obj_type == 's' ? &mp_type_str : &mp_type_bytes, &vstr);
pythontech 0:5868e8752d44 281 } else if (obj_type == 'i') {
pythontech 0:5868e8752d44 282 return mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL);
pythontech 0:5868e8752d44 283 } else {
pythontech 0:5868e8752d44 284 assert(obj_type == 'f' || obj_type == 'c');
pythontech 0:5868e8752d44 285 return mp_parse_num_decimal(vstr.buf, vstr.len, obj_type == 'c', false, NULL);
pythontech 0:5868e8752d44 286 }
pythontech 0:5868e8752d44 287 }
pythontech 0:5868e8752d44 288 }
pythontech 0:5868e8752d44 289
pythontech 0:5868e8752d44 290 STATIC void load_bytecode_qstrs(mp_reader_t *reader, byte *ip, byte *ip_top) {
pythontech 0:5868e8752d44 291 while (ip < ip_top) {
pythontech 0:5868e8752d44 292 size_t sz;
pythontech 0:5868e8752d44 293 uint f = mp_opcode_format(ip, &sz);
pythontech 0:5868e8752d44 294 if (f == MP_OPCODE_QSTR) {
pythontech 0:5868e8752d44 295 qstr qst = load_qstr(reader);
pythontech 0:5868e8752d44 296 ip[1] = qst;
pythontech 0:5868e8752d44 297 ip[2] = qst >> 8;
pythontech 0:5868e8752d44 298 }
pythontech 0:5868e8752d44 299 ip += sz;
pythontech 0:5868e8752d44 300 }
pythontech 0:5868e8752d44 301 }
pythontech 0:5868e8752d44 302
pythontech 0:5868e8752d44 303 STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader) {
pythontech 0:5868e8752d44 304 // load bytecode
pythontech 0:5868e8752d44 305 mp_uint_t bc_len = read_uint(reader);
pythontech 0:5868e8752d44 306 byte *bytecode = m_new(byte, bc_len);
pythontech 0:5868e8752d44 307 read_bytes(reader, bytecode, bc_len);
pythontech 0:5868e8752d44 308
pythontech 0:5868e8752d44 309 // extract prelude
pythontech 0:5868e8752d44 310 const byte *ip = bytecode;
pythontech 0:5868e8752d44 311 const byte *ip2;
pythontech 0:5868e8752d44 312 bytecode_prelude_t prelude;
pythontech 0:5868e8752d44 313 extract_prelude(&ip, &ip2, &prelude);
pythontech 0:5868e8752d44 314
pythontech 0:5868e8752d44 315 // load qstrs and link global qstr ids into bytecode
pythontech 0:5868e8752d44 316 qstr simple_name = load_qstr(reader);
pythontech 0:5868e8752d44 317 qstr source_file = load_qstr(reader);
pythontech 0:5868e8752d44 318 ((byte*)ip2)[0] = simple_name; ((byte*)ip2)[1] = simple_name >> 8;
pythontech 0:5868e8752d44 319 ((byte*)ip2)[2] = source_file; ((byte*)ip2)[3] = source_file >> 8;
pythontech 0:5868e8752d44 320 load_bytecode_qstrs(reader, (byte*)ip, bytecode + bc_len);
pythontech 0:5868e8752d44 321
pythontech 0:5868e8752d44 322 // load constant table
pythontech 0:5868e8752d44 323 mp_uint_t n_obj = read_uint(reader);
pythontech 0:5868e8752d44 324 mp_uint_t n_raw_code = read_uint(reader);
pythontech 0:5868e8752d44 325 mp_uint_t *const_table = m_new(mp_uint_t, prelude.n_pos_args + prelude.n_kwonly_args + n_obj + n_raw_code);
pythontech 0:5868e8752d44 326 mp_uint_t *ct = const_table;
pythontech 0:5868e8752d44 327 for (mp_uint_t i = 0; i < prelude.n_pos_args + prelude.n_kwonly_args; ++i) {
pythontech 0:5868e8752d44 328 *ct++ = (mp_uint_t)MP_OBJ_NEW_QSTR(load_qstr(reader));
pythontech 0:5868e8752d44 329 }
pythontech 0:5868e8752d44 330 for (mp_uint_t i = 0; i < n_obj; ++i) {
pythontech 0:5868e8752d44 331 *ct++ = (mp_uint_t)load_obj(reader);
pythontech 0:5868e8752d44 332 }
pythontech 0:5868e8752d44 333 for (mp_uint_t i = 0; i < n_raw_code; ++i) {
pythontech 0:5868e8752d44 334 *ct++ = (mp_uint_t)(uintptr_t)load_raw_code(reader);
pythontech 0:5868e8752d44 335 }
pythontech 0:5868e8752d44 336
pythontech 0:5868e8752d44 337 // create raw_code and return it
pythontech 0:5868e8752d44 338 mp_raw_code_t *rc = mp_emit_glue_new_raw_code();
pythontech 0:5868e8752d44 339 mp_emit_glue_assign_bytecode(rc, bytecode, bc_len, const_table,
pythontech 0:5868e8752d44 340 #if MICROPY_PERSISTENT_CODE_SAVE
pythontech 0:5868e8752d44 341 n_obj, n_raw_code,
pythontech 0:5868e8752d44 342 #endif
pythontech 0:5868e8752d44 343 prelude.scope_flags);
pythontech 0:5868e8752d44 344 return rc;
pythontech 0:5868e8752d44 345 }
pythontech 0:5868e8752d44 346
pythontech 0:5868e8752d44 347 mp_raw_code_t *mp_raw_code_load(mp_reader_t *reader) {
pythontech 0:5868e8752d44 348 byte header[4];
pythontech 0:5868e8752d44 349 read_bytes(reader, header, sizeof(header));
pythontech 0:5868e8752d44 350 if (strncmp((char*)header, "M\x00", 2) != 0) {
pythontech 0:5868e8752d44 351 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
pythontech 0:5868e8752d44 352 "invalid .mpy file"));
pythontech 0:5868e8752d44 353 }
pythontech 0:5868e8752d44 354 if (header[2] != MPY_FEATURE_FLAGS || header[3] > mp_small_int_bits()) {
pythontech 0:5868e8752d44 355 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
pythontech 0:5868e8752d44 356 "incompatible .mpy file"));
pythontech 0:5868e8752d44 357 }
pythontech 0:5868e8752d44 358 return load_raw_code(reader);
pythontech 0:5868e8752d44 359 }
pythontech 0:5868e8752d44 360
pythontech 0:5868e8752d44 361 typedef struct _mp_mem_reader_t {
pythontech 0:5868e8752d44 362 const byte *cur;
pythontech 0:5868e8752d44 363 const byte *end;
pythontech 0:5868e8752d44 364 } mp_mem_reader_t;
pythontech 0:5868e8752d44 365
pythontech 0:5868e8752d44 366 STATIC mp_uint_t mp_mem_reader_next_byte(void *br_in) {
pythontech 0:5868e8752d44 367 mp_mem_reader_t *br = br_in;
pythontech 0:5868e8752d44 368 if (br->cur < br->end) {
pythontech 0:5868e8752d44 369 return *br->cur++;
pythontech 0:5868e8752d44 370 } else {
pythontech 0:5868e8752d44 371 return (mp_uint_t)-1;
pythontech 0:5868e8752d44 372 }
pythontech 0:5868e8752d44 373 }
pythontech 0:5868e8752d44 374
pythontech 0:5868e8752d44 375 mp_raw_code_t *mp_raw_code_load_mem(const byte *buf, size_t len) {
pythontech 0:5868e8752d44 376 mp_mem_reader_t mr = {buf, buf + len};
pythontech 0:5868e8752d44 377 mp_reader_t reader = {&mr, mp_mem_reader_next_byte};
pythontech 0:5868e8752d44 378 return mp_raw_code_load(&reader);
pythontech 0:5868e8752d44 379 }
pythontech 0:5868e8752d44 380
pythontech 0:5868e8752d44 381 // here we define mp_raw_code_load_file depending on the port
pythontech 0:5868e8752d44 382 // TODO abstract this away properly
pythontech 0:5868e8752d44 383
pythontech 0:5868e8752d44 384 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm__) && (defined(__unix__)))
pythontech 0:5868e8752d44 385 // unix file reader
pythontech 0:5868e8752d44 386
pythontech 0:5868e8752d44 387 #include <sys/stat.h>
pythontech 0:5868e8752d44 388 #include <fcntl.h>
pythontech 0:5868e8752d44 389 #include <unistd.h>
pythontech 0:5868e8752d44 390
pythontech 0:5868e8752d44 391 typedef struct _mp_lexer_file_buf_t {
pythontech 0:5868e8752d44 392 int fd;
pythontech 0:5868e8752d44 393 byte buf[20];
pythontech 0:5868e8752d44 394 mp_uint_t len;
pythontech 0:5868e8752d44 395 mp_uint_t pos;
pythontech 0:5868e8752d44 396 } mp_lexer_file_buf_t;
pythontech 0:5868e8752d44 397
pythontech 0:5868e8752d44 398 STATIC mp_uint_t file_buf_next_byte(void *fb_in) {
pythontech 0:5868e8752d44 399 mp_lexer_file_buf_t *fb = fb_in;
pythontech 0:5868e8752d44 400 if (fb->pos >= fb->len) {
pythontech 0:5868e8752d44 401 if (fb->len == 0) {
pythontech 0:5868e8752d44 402 return (mp_uint_t)-1;
pythontech 0:5868e8752d44 403 } else {
pythontech 0:5868e8752d44 404 int n = read(fb->fd, fb->buf, sizeof(fb->buf));
pythontech 0:5868e8752d44 405 if (n <= 0) {
pythontech 0:5868e8752d44 406 fb->len = 0;
pythontech 0:5868e8752d44 407 return (mp_uint_t)-1;
pythontech 0:5868e8752d44 408 }
pythontech 0:5868e8752d44 409 fb->len = n;
pythontech 0:5868e8752d44 410 fb->pos = 0;
pythontech 0:5868e8752d44 411 }
pythontech 0:5868e8752d44 412 }
pythontech 0:5868e8752d44 413 return fb->buf[fb->pos++];
pythontech 0:5868e8752d44 414 }
pythontech 0:5868e8752d44 415
pythontech 0:5868e8752d44 416 mp_raw_code_t *mp_raw_code_load_file(const char *filename) {
pythontech 0:5868e8752d44 417 mp_lexer_file_buf_t fb;
pythontech 0:5868e8752d44 418 fb.fd = open(filename, O_RDONLY, 0644);
pythontech 0:5868e8752d44 419 int n = read(fb.fd, fb.buf, sizeof(fb.buf));
pythontech 0:5868e8752d44 420 fb.len = n;
pythontech 0:5868e8752d44 421 fb.pos = 0;
pythontech 0:5868e8752d44 422 mp_reader_t reader;
pythontech 0:5868e8752d44 423 reader.data = &fb;
pythontech 0:5868e8752d44 424 reader.read_byte = file_buf_next_byte;
pythontech 0:5868e8752d44 425 mp_raw_code_t *rc = mp_raw_code_load(&reader);
pythontech 0:5868e8752d44 426 close(fb.fd);
pythontech 0:5868e8752d44 427 return rc;
pythontech 0:5868e8752d44 428 }
pythontech 0:5868e8752d44 429
pythontech 0:5868e8752d44 430 #elif defined(__thumb2__)
pythontech 0:5868e8752d44 431 // fatfs file reader (assume thumb2 arch uses fatfs...)
pythontech 0:5868e8752d44 432
pythontech 0:5868e8752d44 433 #include "lib/fatfs/ff.h"
pythontech 0:5868e8752d44 434
pythontech 0:5868e8752d44 435 typedef struct _mp_lexer_file_buf_t {
pythontech 0:5868e8752d44 436 FIL fp;
pythontech 0:5868e8752d44 437 byte buf[20];
pythontech 0:5868e8752d44 438 uint16_t len;
pythontech 0:5868e8752d44 439 uint16_t pos;
pythontech 0:5868e8752d44 440 } mp_lexer_file_buf_t;
pythontech 0:5868e8752d44 441
pythontech 0:5868e8752d44 442 STATIC mp_uint_t file_buf_next_byte(void *fb_in) {
pythontech 0:5868e8752d44 443 mp_lexer_file_buf_t *fb = fb_in;
pythontech 0:5868e8752d44 444 if (fb->pos >= fb->len) {
pythontech 0:5868e8752d44 445 if (fb->len < sizeof(fb->buf)) {
pythontech 0:5868e8752d44 446 return (mp_uint_t)-1;
pythontech 0:5868e8752d44 447 } else {
pythontech 0:5868e8752d44 448 UINT n;
pythontech 0:5868e8752d44 449 f_read(&fb->fp, fb->buf, sizeof(fb->buf), &n);
pythontech 0:5868e8752d44 450 if (n == 0) {
pythontech 0:5868e8752d44 451 return (mp_uint_t)-1;
pythontech 0:5868e8752d44 452 }
pythontech 0:5868e8752d44 453 fb->len = n;
pythontech 0:5868e8752d44 454 fb->pos = 0;
pythontech 0:5868e8752d44 455 }
pythontech 0:5868e8752d44 456 }
pythontech 0:5868e8752d44 457 return fb->buf[fb->pos++];
pythontech 0:5868e8752d44 458 }
pythontech 0:5868e8752d44 459
pythontech 0:5868e8752d44 460 mp_raw_code_t *mp_raw_code_load_file(const char *filename) {
pythontech 0:5868e8752d44 461 mp_lexer_file_buf_t fb;
pythontech 0:5868e8752d44 462 /*FRESULT res =*/ f_open(&fb.fp, filename, FA_READ);
pythontech 0:5868e8752d44 463 UINT n;
pythontech 0:5868e8752d44 464 f_read(&fb.fp, fb.buf, sizeof(fb.buf), &n);
pythontech 0:5868e8752d44 465 fb.len = n;
pythontech 0:5868e8752d44 466 fb.pos = 0;
pythontech 0:5868e8752d44 467
pythontech 0:5868e8752d44 468 mp_reader_t reader;
pythontech 0:5868e8752d44 469 reader.data = &fb;
pythontech 0:5868e8752d44 470 reader.read_byte = file_buf_next_byte;
pythontech 0:5868e8752d44 471 mp_raw_code_t *rc = mp_raw_code_load(&reader);
pythontech 0:5868e8752d44 472
pythontech 0:5868e8752d44 473 f_close(&fb.fp);
pythontech 0:5868e8752d44 474
pythontech 0:5868e8752d44 475 return rc;
pythontech 0:5868e8752d44 476 }
pythontech 0:5868e8752d44 477
pythontech 0:5868e8752d44 478 #endif
pythontech 0:5868e8752d44 479
pythontech 0:5868e8752d44 480 #endif // MICROPY_PERSISTENT_CODE_LOAD
pythontech 0:5868e8752d44 481
pythontech 0:5868e8752d44 482 #if MICROPY_PERSISTENT_CODE_SAVE
pythontech 0:5868e8752d44 483
pythontech 0:5868e8752d44 484 #include "py/objstr.h"
pythontech 0:5868e8752d44 485
pythontech 0:5868e8752d44 486 STATIC void mp_print_bytes(mp_print_t *print, const byte *data, size_t len) {
pythontech 0:5868e8752d44 487 print->print_strn(print->data, (const char*)data, len);
pythontech 0:5868e8752d44 488 }
pythontech 0:5868e8752d44 489
pythontech 0:5868e8752d44 490 #define BYTES_FOR_INT ((BYTES_PER_WORD * 8 + 6) / 7)
pythontech 0:5868e8752d44 491 STATIC void mp_print_uint(mp_print_t *print, mp_uint_t n) {
pythontech 0:5868e8752d44 492 byte buf[BYTES_FOR_INT];
pythontech 0:5868e8752d44 493 byte *p = buf + sizeof(buf);
pythontech 0:5868e8752d44 494 *--p = n & 0x7f;
pythontech 0:5868e8752d44 495 n >>= 7;
pythontech 0:5868e8752d44 496 for (; n != 0; n >>= 7) {
pythontech 0:5868e8752d44 497 *--p = 0x80 | (n & 0x7f);
pythontech 0:5868e8752d44 498 }
pythontech 0:5868e8752d44 499 print->print_strn(print->data, (char*)p, buf + sizeof(buf) - p);
pythontech 0:5868e8752d44 500 }
pythontech 0:5868e8752d44 501
pythontech 0:5868e8752d44 502 STATIC void save_qstr(mp_print_t *print, qstr qst) {
pythontech 0:5868e8752d44 503 size_t len;
pythontech 0:5868e8752d44 504 const byte *str = qstr_data(qst, &len);
pythontech 0:5868e8752d44 505 mp_print_uint(print, len);
pythontech 0:5868e8752d44 506 mp_print_bytes(print, str, len);
pythontech 0:5868e8752d44 507 }
pythontech 0:5868e8752d44 508
pythontech 0:5868e8752d44 509 STATIC void save_obj(mp_print_t *print, mp_obj_t o) {
pythontech 0:5868e8752d44 510 if (MP_OBJ_IS_STR_OR_BYTES(o)) {
pythontech 0:5868e8752d44 511 byte obj_type;
pythontech 0:5868e8752d44 512 if (MP_OBJ_IS_STR(o)) {
pythontech 0:5868e8752d44 513 obj_type = 's';
pythontech 0:5868e8752d44 514 } else {
pythontech 0:5868e8752d44 515 obj_type = 'b';
pythontech 0:5868e8752d44 516 }
pythontech 0:5868e8752d44 517 mp_uint_t len;
pythontech 0:5868e8752d44 518 const char *str = mp_obj_str_get_data(o, &len);
pythontech 0:5868e8752d44 519 mp_print_bytes(print, &obj_type, 1);
pythontech 0:5868e8752d44 520 mp_print_uint(print, len);
pythontech 0:5868e8752d44 521 mp_print_bytes(print, (const byte*)str, len);
pythontech 0:5868e8752d44 522 } else if (MP_OBJ_TO_PTR(o) == &mp_const_ellipsis_obj) {
pythontech 0:5868e8752d44 523 byte obj_type = 'e';
pythontech 0:5868e8752d44 524 mp_print_bytes(print, &obj_type, 1);
pythontech 0:5868e8752d44 525 } else {
pythontech 0:5868e8752d44 526 // we save numbers using a simplistic text representation
pythontech 0:5868e8752d44 527 // TODO could be improved
pythontech 0:5868e8752d44 528 byte obj_type;
pythontech 0:5868e8752d44 529 if (MP_OBJ_IS_TYPE(o, &mp_type_int)) {
pythontech 0:5868e8752d44 530 obj_type = 'i';
pythontech 0:5868e8752d44 531 } else if (mp_obj_is_float(o)) {
pythontech 0:5868e8752d44 532 obj_type = 'f';
pythontech 0:5868e8752d44 533 } else {
pythontech 0:5868e8752d44 534 assert(MP_OBJ_IS_TYPE(o, &mp_type_complex));
pythontech 0:5868e8752d44 535 obj_type = 'c';
pythontech 0:5868e8752d44 536 }
pythontech 0:5868e8752d44 537 vstr_t vstr;
pythontech 0:5868e8752d44 538 mp_print_t pr;
pythontech 0:5868e8752d44 539 vstr_init_print(&vstr, 10, &pr);
pythontech 0:5868e8752d44 540 mp_obj_print_helper(&pr, o, PRINT_REPR);
pythontech 0:5868e8752d44 541 mp_print_bytes(print, &obj_type, 1);
pythontech 0:5868e8752d44 542 mp_print_uint(print, vstr.len);
pythontech 0:5868e8752d44 543 mp_print_bytes(print, (const byte*)vstr.buf, vstr.len);
pythontech 0:5868e8752d44 544 vstr_clear(&vstr);
pythontech 0:5868e8752d44 545 }
pythontech 0:5868e8752d44 546 }
pythontech 0:5868e8752d44 547
pythontech 0:5868e8752d44 548 STATIC void save_bytecode_qstrs(mp_print_t *print, const byte *ip, const byte *ip_top) {
pythontech 0:5868e8752d44 549 while (ip < ip_top) {
pythontech 0:5868e8752d44 550 size_t sz;
pythontech 0:5868e8752d44 551 uint f = mp_opcode_format(ip, &sz);
pythontech 0:5868e8752d44 552 if (f == MP_OPCODE_QSTR) {
pythontech 0:5868e8752d44 553 qstr qst = ip[1] | (ip[2] << 8);
pythontech 0:5868e8752d44 554 save_qstr(print, qst);
pythontech 0:5868e8752d44 555 }
pythontech 0:5868e8752d44 556 ip += sz;
pythontech 0:5868e8752d44 557 }
pythontech 0:5868e8752d44 558 }
pythontech 0:5868e8752d44 559
pythontech 0:5868e8752d44 560 STATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc) {
pythontech 0:5868e8752d44 561 if (rc->kind != MP_CODE_BYTECODE) {
pythontech 0:5868e8752d44 562 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
pythontech 0:5868e8752d44 563 "can only save bytecode"));
pythontech 0:5868e8752d44 564 }
pythontech 0:5868e8752d44 565
pythontech 0:5868e8752d44 566 // save bytecode
pythontech 0:5868e8752d44 567 mp_print_uint(print, rc->data.u_byte.bc_len);
pythontech 0:5868e8752d44 568 mp_print_bytes(print, rc->data.u_byte.bytecode, rc->data.u_byte.bc_len);
pythontech 0:5868e8752d44 569
pythontech 0:5868e8752d44 570 // extract prelude
pythontech 0:5868e8752d44 571 const byte *ip = rc->data.u_byte.bytecode;
pythontech 0:5868e8752d44 572 const byte *ip2;
pythontech 0:5868e8752d44 573 bytecode_prelude_t prelude;
pythontech 0:5868e8752d44 574 extract_prelude(&ip, &ip2, &prelude);
pythontech 0:5868e8752d44 575
pythontech 0:5868e8752d44 576 // save qstrs
pythontech 0:5868e8752d44 577 save_qstr(print, ip2[0] | (ip2[1] << 8)); // simple_name
pythontech 0:5868e8752d44 578 save_qstr(print, ip2[2] | (ip2[3] << 8)); // source_file
pythontech 0:5868e8752d44 579 save_bytecode_qstrs(print, ip, rc->data.u_byte.bytecode + rc->data.u_byte.bc_len);
pythontech 0:5868e8752d44 580
pythontech 0:5868e8752d44 581 // save constant table
pythontech 0:5868e8752d44 582 mp_print_uint(print, rc->data.u_byte.n_obj);
pythontech 0:5868e8752d44 583 mp_print_uint(print, rc->data.u_byte.n_raw_code);
pythontech 0:5868e8752d44 584 const mp_uint_t *const_table = rc->data.u_byte.const_table;
pythontech 0:5868e8752d44 585 for (uint i = 0; i < prelude.n_pos_args + prelude.n_kwonly_args; ++i) {
pythontech 0:5868e8752d44 586 mp_obj_t o = (mp_obj_t)*const_table++;
pythontech 0:5868e8752d44 587 save_qstr(print, MP_OBJ_QSTR_VALUE(o));
pythontech 0:5868e8752d44 588 }
pythontech 0:5868e8752d44 589 for (uint i = 0; i < rc->data.u_byte.n_obj; ++i) {
pythontech 0:5868e8752d44 590 save_obj(print, (mp_obj_t)*const_table++);
pythontech 0:5868e8752d44 591 }
pythontech 0:5868e8752d44 592 for (uint i = 0; i < rc->data.u_byte.n_raw_code; ++i) {
pythontech 0:5868e8752d44 593 save_raw_code(print, (mp_raw_code_t*)(uintptr_t)*const_table++);
pythontech 0:5868e8752d44 594 }
pythontech 0:5868e8752d44 595 }
pythontech 0:5868e8752d44 596
pythontech 0:5868e8752d44 597 void mp_raw_code_save(mp_raw_code_t *rc, mp_print_t *print) {
pythontech 0:5868e8752d44 598 // header contains:
pythontech 0:5868e8752d44 599 // byte 'M'
pythontech 0:5868e8752d44 600 // byte version
pythontech 0:5868e8752d44 601 // byte feature flags
pythontech 0:5868e8752d44 602 // byte number of bits in a small int
pythontech 0:5868e8752d44 603 byte header[4] = {'M', 0, MPY_FEATURE_FLAGS_DYNAMIC,
pythontech 0:5868e8752d44 604 #if MICROPY_DYNAMIC_COMPILER
pythontech 0:5868e8752d44 605 mp_dynamic_compiler.small_int_bits,
pythontech 0:5868e8752d44 606 #else
pythontech 0:5868e8752d44 607 mp_small_int_bits(),
pythontech 0:5868e8752d44 608 #endif
pythontech 0:5868e8752d44 609 };
pythontech 0:5868e8752d44 610 mp_print_bytes(print, header, sizeof(header));
pythontech 0:5868e8752d44 611
pythontech 0:5868e8752d44 612 save_raw_code(print, rc);
pythontech 0:5868e8752d44 613 }
pythontech 0:5868e8752d44 614
pythontech 0:5868e8752d44 615 // here we define mp_raw_code_save_file depending on the port
pythontech 0:5868e8752d44 616 // TODO abstract this away properly
pythontech 0:5868e8752d44 617
pythontech 0:5868e8752d44 618 #if defined(__i386__) || defined(__x86_64__) || (defined(__arm__) && (defined(__unix__)))
pythontech 0:5868e8752d44 619
pythontech 0:5868e8752d44 620 #include <unistd.h>
pythontech 0:5868e8752d44 621 #include <sys/stat.h>
pythontech 0:5868e8752d44 622 #include <fcntl.h>
pythontech 0:5868e8752d44 623
pythontech 0:5868e8752d44 624 STATIC void fd_print_strn(void *env, const char *str, size_t len) {
pythontech 0:5868e8752d44 625 int fd = (intptr_t)env;
pythontech 0:5868e8752d44 626 ssize_t ret = write(fd, str, len);
pythontech 0:5868e8752d44 627 (void)ret;
pythontech 0:5868e8752d44 628 }
pythontech 0:5868e8752d44 629
pythontech 0:5868e8752d44 630 void mp_raw_code_save_file(mp_raw_code_t *rc, const char *filename) {
pythontech 0:5868e8752d44 631 int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
pythontech 0:5868e8752d44 632 mp_print_t fd_print = {(void*)(intptr_t)fd, fd_print_strn};
pythontech 0:5868e8752d44 633 mp_raw_code_save(rc, &fd_print);
pythontech 0:5868e8752d44 634 close(fd);
pythontech 0:5868e8752d44 635 }
pythontech 0:5868e8752d44 636
pythontech 0:5868e8752d44 637 #else
pythontech 0:5868e8752d44 638 #error mp_raw_code_save_file not implemented for this platform
pythontech 0:5868e8752d44 639 #endif
pythontech 0:5868e8752d44 640
pythontech 0:5868e8752d44 641 #endif // MICROPY_PERSISTENT_CODE_SAVE