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 #include <assert.h>
pythontech 0:5868e8752d44 28 #include <string.h>
pythontech 0:5868e8752d44 29 #include <stdio.h>
pythontech 0:5868e8752d44 30
pythontech 0:5868e8752d44 31 #include "py/mpstate.h"
pythontech 0:5868e8752d44 32 #include "py/qstr.h"
pythontech 0:5868e8752d44 33 #include "py/gc.h"
pythontech 0:5868e8752d44 34
pythontech 0:5868e8752d44 35 // NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings)
pythontech 0:5868e8752d44 36 // ultimately we will replace this with a static hash table of some kind
pythontech 0:5868e8752d44 37 // also probably need to include the length in the string data, to allow null bytes in the string
pythontech 0:5868e8752d44 38
pythontech 0:5868e8752d44 39 #if 0 // print debugging info
pythontech 0:5868e8752d44 40 #define DEBUG_printf DEBUG_printf
pythontech 0:5868e8752d44 41 #else // don't print debugging info
pythontech 0:5868e8752d44 42 #define DEBUG_printf(...) (void)0
pythontech 0:5868e8752d44 43 #endif
pythontech 0:5868e8752d44 44
pythontech 0:5868e8752d44 45 // A qstr is an index into the qstr pool.
pythontech 0:5868e8752d44 46 // The data for a qstr contains (hash, length, data):
pythontech 0:5868e8752d44 47 // - hash (configurable number of bytes)
pythontech 0:5868e8752d44 48 // - length (configurable number of bytes)
pythontech 0:5868e8752d44 49 // - data ("length" number of bytes)
pythontech 0:5868e8752d44 50 // - \0 terminated (so they can be printed using printf)
pythontech 0:5868e8752d44 51
pythontech 0:5868e8752d44 52 #if MICROPY_QSTR_BYTES_IN_HASH == 1
pythontech 0:5868e8752d44 53 #define Q_HASH_MASK (0xff)
pythontech 0:5868e8752d44 54 #define Q_GET_HASH(q) ((mp_uint_t)(q)[0])
pythontech 0:5868e8752d44 55 #define Q_SET_HASH(q, hash) do { (q)[0] = (hash); } while (0)
pythontech 0:5868e8752d44 56 #elif MICROPY_QSTR_BYTES_IN_HASH == 2
pythontech 0:5868e8752d44 57 #define Q_HASH_MASK (0xffff)
pythontech 0:5868e8752d44 58 #define Q_GET_HASH(q) ((mp_uint_t)(q)[0] | ((mp_uint_t)(q)[1] << 8))
pythontech 0:5868e8752d44 59 #define Q_SET_HASH(q, hash) do { (q)[0] = (hash); (q)[1] = (hash) >> 8; } while (0)
pythontech 0:5868e8752d44 60 #else
pythontech 0:5868e8752d44 61 #error unimplemented qstr hash decoding
pythontech 0:5868e8752d44 62 #endif
pythontech 0:5868e8752d44 63 #define Q_GET_ALLOC(q) (MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + Q_GET_LENGTH(q) + 1)
pythontech 0:5868e8752d44 64 #define Q_GET_DATA(q) ((q) + MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN)
pythontech 0:5868e8752d44 65 #if MICROPY_QSTR_BYTES_IN_LEN == 1
pythontech 0:5868e8752d44 66 #define Q_GET_LENGTH(q) ((q)[MICROPY_QSTR_BYTES_IN_HASH])
pythontech 0:5868e8752d44 67 #define Q_SET_LENGTH(q, len) do { (q)[MICROPY_QSTR_BYTES_IN_HASH] = (len); } while (0)
pythontech 0:5868e8752d44 68 #elif MICROPY_QSTR_BYTES_IN_LEN == 2
pythontech 0:5868e8752d44 69 #define Q_GET_LENGTH(q) ((q)[MICROPY_QSTR_BYTES_IN_HASH] | ((q)[MICROPY_QSTR_BYTES_IN_HASH + 1] << 8))
pythontech 0:5868e8752d44 70 #define Q_SET_LENGTH(q, len) do { (q)[MICROPY_QSTR_BYTES_IN_HASH] = (len); (q)[MICROPY_QSTR_BYTES_IN_HASH + 1] = (len) >> 8; } while (0)
pythontech 0:5868e8752d44 71 #else
pythontech 0:5868e8752d44 72 #error unimplemented qstr length decoding
pythontech 0:5868e8752d44 73 #endif
pythontech 0:5868e8752d44 74
pythontech 0:5868e8752d44 75 // this must match the equivalent function in makeqstrdata.py
pythontech 0:5868e8752d44 76 mp_uint_t qstr_compute_hash(const byte *data, size_t len) {
pythontech 0:5868e8752d44 77 // djb2 algorithm; see http://www.cse.yorku.ca/~oz/hash.html
pythontech 0:5868e8752d44 78 mp_uint_t hash = 5381;
pythontech 0:5868e8752d44 79 for (const byte *top = data + len; data < top; data++) {
pythontech 0:5868e8752d44 80 hash = ((hash << 5) + hash) ^ (*data); // hash * 33 ^ data
pythontech 0:5868e8752d44 81 }
pythontech 0:5868e8752d44 82 hash &= Q_HASH_MASK;
pythontech 0:5868e8752d44 83 // Make sure that valid hash is never zero, zero means "hash not computed"
pythontech 0:5868e8752d44 84 if (hash == 0) {
pythontech 0:5868e8752d44 85 hash++;
pythontech 0:5868e8752d44 86 }
pythontech 0:5868e8752d44 87 return hash;
pythontech 0:5868e8752d44 88 }
pythontech 0:5868e8752d44 89
Colin Hogben 2:c89e95946844 90 const qstr_pool_t mp_qstr_const_pool = {
pythontech 0:5868e8752d44 91 NULL, // no previous pool
pythontech 0:5868e8752d44 92 0, // no previous pool
pythontech 0:5868e8752d44 93 10, // set so that the first dynamically allocated pool is twice this size; must be <= the len (just below)
Colin Hogben 2:c89e95946844 94 MP_QSTRnumber_of, // corresponds to number of strings in array just below
pythontech 0:5868e8752d44 95 {
pythontech 0:5868e8752d44 96 #define QDEF(id, str) str,
pythontech 0:5868e8752d44 97 #include "genhdr/qstrdefs.generated.h"
pythontech 0:5868e8752d44 98 #undef QDEF
pythontech 0:5868e8752d44 99 },
pythontech 0:5868e8752d44 100 };
pythontech 0:5868e8752d44 101
Colin Hogben 2:c89e95946844 102 #ifdef MICROPY_QSTR_EXTRA_POOL
Colin Hogben 2:c89e95946844 103 extern const qstr_pool_t MICROPY_QSTR_EXTRA_POOL;
Colin Hogben 2:c89e95946844 104 #define CONST_POOL MICROPY_QSTR_EXTRA_POOL
Colin Hogben 2:c89e95946844 105 #else
Colin Hogben 2:c89e95946844 106 #define CONST_POOL mp_qstr_const_pool
Colin Hogben 2:c89e95946844 107 #endif
Colin Hogben 2:c89e95946844 108
pythontech 0:5868e8752d44 109 void qstr_init(void) {
Colin Hogben 2:c89e95946844 110 MP_STATE_VM(last_pool) = (qstr_pool_t*)&CONST_POOL; // we won't modify the const_pool since it has no allocated room left
pythontech 0:5868e8752d44 111 MP_STATE_VM(qstr_last_chunk) = NULL;
pythontech 0:5868e8752d44 112 }
pythontech 0:5868e8752d44 113
pythontech 0:5868e8752d44 114 STATIC const byte *find_qstr(qstr q) {
pythontech 0:5868e8752d44 115 // search pool for this qstr
pythontech 0:5868e8752d44 116 for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL; pool = pool->prev) {
pythontech 0:5868e8752d44 117 if (q >= pool->total_prev_len) {
pythontech 0:5868e8752d44 118 return pool->qstrs[q - pool->total_prev_len];
pythontech 0:5868e8752d44 119 }
pythontech 0:5868e8752d44 120 }
pythontech 0:5868e8752d44 121
pythontech 0:5868e8752d44 122 // not found
pythontech 0:5868e8752d44 123 return 0;
pythontech 0:5868e8752d44 124 }
pythontech 0:5868e8752d44 125
pythontech 0:5868e8752d44 126 STATIC qstr qstr_add(const byte *q_ptr) {
pythontech 0:5868e8752d44 127 DEBUG_printf("QSTR: add hash=%d len=%d data=%.*s\n", Q_GET_HASH(q_ptr), Q_GET_LENGTH(q_ptr), Q_GET_LENGTH(q_ptr), Q_GET_DATA(q_ptr));
pythontech 0:5868e8752d44 128
pythontech 0:5868e8752d44 129 // make sure we have room in the pool for a new qstr
pythontech 0:5868e8752d44 130 if (MP_STATE_VM(last_pool)->len >= MP_STATE_VM(last_pool)->alloc) {
pythontech 0:5868e8752d44 131 qstr_pool_t *pool = m_new_obj_var(qstr_pool_t, const char*, MP_STATE_VM(last_pool)->alloc * 2);
pythontech 0:5868e8752d44 132 pool->prev = MP_STATE_VM(last_pool);
pythontech 0:5868e8752d44 133 pool->total_prev_len = MP_STATE_VM(last_pool)->total_prev_len + MP_STATE_VM(last_pool)->len;
pythontech 0:5868e8752d44 134 pool->alloc = MP_STATE_VM(last_pool)->alloc * 2;
pythontech 0:5868e8752d44 135 pool->len = 0;
pythontech 0:5868e8752d44 136 MP_STATE_VM(last_pool) = pool;
pythontech 0:5868e8752d44 137 DEBUG_printf("QSTR: allocate new pool of size %d\n", MP_STATE_VM(last_pool)->alloc);
pythontech 0:5868e8752d44 138 }
pythontech 0:5868e8752d44 139
pythontech 0:5868e8752d44 140 // add the new qstr
pythontech 0:5868e8752d44 141 MP_STATE_VM(last_pool)->qstrs[MP_STATE_VM(last_pool)->len++] = q_ptr;
pythontech 0:5868e8752d44 142
pythontech 0:5868e8752d44 143 // return id for the newly-added qstr
pythontech 0:5868e8752d44 144 return MP_STATE_VM(last_pool)->total_prev_len + MP_STATE_VM(last_pool)->len - 1;
pythontech 0:5868e8752d44 145 }
pythontech 0:5868e8752d44 146
pythontech 0:5868e8752d44 147 qstr qstr_find_strn(const char *str, size_t str_len) {
pythontech 0:5868e8752d44 148 // work out hash of str
pythontech 0:5868e8752d44 149 mp_uint_t str_hash = qstr_compute_hash((const byte*)str, str_len);
pythontech 0:5868e8752d44 150
pythontech 0:5868e8752d44 151 // search pools for the data
pythontech 0:5868e8752d44 152 for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL; pool = pool->prev) {
pythontech 0:5868e8752d44 153 for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) {
pythontech 0:5868e8752d44 154 if (Q_GET_HASH(*q) == str_hash && Q_GET_LENGTH(*q) == str_len && memcmp(Q_GET_DATA(*q), str, str_len) == 0) {
pythontech 0:5868e8752d44 155 return pool->total_prev_len + (q - pool->qstrs);
pythontech 0:5868e8752d44 156 }
pythontech 0:5868e8752d44 157 }
pythontech 0:5868e8752d44 158 }
pythontech 0:5868e8752d44 159
pythontech 0:5868e8752d44 160 // not found; return null qstr
pythontech 0:5868e8752d44 161 return 0;
pythontech 0:5868e8752d44 162 }
pythontech 0:5868e8752d44 163
pythontech 0:5868e8752d44 164 qstr qstr_from_str(const char *str) {
pythontech 0:5868e8752d44 165 return qstr_from_strn(str, strlen(str));
pythontech 0:5868e8752d44 166 }
pythontech 0:5868e8752d44 167
pythontech 0:5868e8752d44 168 qstr qstr_from_strn(const char *str, size_t len) {
pythontech 0:5868e8752d44 169 assert(len < (1 << (8 * MICROPY_QSTR_BYTES_IN_LEN)));
pythontech 0:5868e8752d44 170 qstr q = qstr_find_strn(str, len);
pythontech 0:5868e8752d44 171 if (q == 0) {
pythontech 0:5868e8752d44 172 // qstr does not exist in interned pool so need to add it
pythontech 0:5868e8752d44 173
pythontech 0:5868e8752d44 174 // compute number of bytes needed to intern this string
pythontech 0:5868e8752d44 175 size_t n_bytes = MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len + 1;
pythontech 0:5868e8752d44 176
pythontech 0:5868e8752d44 177 if (MP_STATE_VM(qstr_last_chunk) != NULL && MP_STATE_VM(qstr_last_used) + n_bytes > MP_STATE_VM(qstr_last_alloc)) {
pythontech 0:5868e8752d44 178 // not enough room at end of previously interned string so try to grow
pythontech 0:5868e8752d44 179 byte *new_p = m_renew_maybe(byte, MP_STATE_VM(qstr_last_chunk), MP_STATE_VM(qstr_last_alloc), MP_STATE_VM(qstr_last_alloc) + n_bytes, false);
pythontech 0:5868e8752d44 180 if (new_p == NULL) {
pythontech 0:5868e8752d44 181 // could not grow existing memory; shrink it to fit previous
pythontech 0:5868e8752d44 182 (void)m_renew(byte, MP_STATE_VM(qstr_last_chunk), MP_STATE_VM(qstr_last_alloc), MP_STATE_VM(qstr_last_used));
pythontech 0:5868e8752d44 183 MP_STATE_VM(qstr_last_chunk) = NULL;
pythontech 0:5868e8752d44 184 } else {
pythontech 0:5868e8752d44 185 // could grow existing memory
pythontech 0:5868e8752d44 186 MP_STATE_VM(qstr_last_alloc) += n_bytes;
pythontech 0:5868e8752d44 187 }
pythontech 0:5868e8752d44 188 }
pythontech 0:5868e8752d44 189
pythontech 0:5868e8752d44 190 if (MP_STATE_VM(qstr_last_chunk) == NULL) {
pythontech 0:5868e8752d44 191 // no existing memory for the interned string so allocate a new chunk
pythontech 0:5868e8752d44 192 size_t al = n_bytes;
pythontech 0:5868e8752d44 193 if (al < MICROPY_ALLOC_QSTR_CHUNK_INIT) {
pythontech 0:5868e8752d44 194 al = MICROPY_ALLOC_QSTR_CHUNK_INIT;
pythontech 0:5868e8752d44 195 }
pythontech 0:5868e8752d44 196 MP_STATE_VM(qstr_last_chunk) = m_new_maybe(byte, al);
pythontech 0:5868e8752d44 197 if (MP_STATE_VM(qstr_last_chunk) == NULL) {
pythontech 0:5868e8752d44 198 // failed to allocate a large chunk so try with exact size
pythontech 0:5868e8752d44 199 MP_STATE_VM(qstr_last_chunk) = m_new(byte, n_bytes);
pythontech 0:5868e8752d44 200 al = n_bytes;
pythontech 0:5868e8752d44 201 }
pythontech 0:5868e8752d44 202 MP_STATE_VM(qstr_last_alloc) = al;
pythontech 0:5868e8752d44 203 MP_STATE_VM(qstr_last_used) = 0;
pythontech 0:5868e8752d44 204 }
pythontech 0:5868e8752d44 205
pythontech 0:5868e8752d44 206 // allocate memory from the chunk for this new interned string's data
pythontech 0:5868e8752d44 207 byte *q_ptr = MP_STATE_VM(qstr_last_chunk) + MP_STATE_VM(qstr_last_used);
pythontech 0:5868e8752d44 208 MP_STATE_VM(qstr_last_used) += n_bytes;
pythontech 0:5868e8752d44 209
pythontech 0:5868e8752d44 210 // store the interned strings' data
pythontech 0:5868e8752d44 211 mp_uint_t hash = qstr_compute_hash((const byte*)str, len);
pythontech 0:5868e8752d44 212 Q_SET_HASH(q_ptr, hash);
pythontech 0:5868e8752d44 213 Q_SET_LENGTH(q_ptr, len);
pythontech 0:5868e8752d44 214 memcpy(q_ptr + MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN, str, len);
pythontech 0:5868e8752d44 215 q_ptr[MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len] = '\0';
pythontech 0:5868e8752d44 216 q = qstr_add(q_ptr);
pythontech 0:5868e8752d44 217 }
pythontech 0:5868e8752d44 218 return q;
pythontech 0:5868e8752d44 219 }
pythontech 0:5868e8752d44 220
pythontech 0:5868e8752d44 221 byte *qstr_build_start(size_t len, byte **q_ptr) {
pythontech 0:5868e8752d44 222 assert(len < (1 << (8 * MICROPY_QSTR_BYTES_IN_LEN)));
pythontech 0:5868e8752d44 223 *q_ptr = m_new(byte, MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len + 1);
pythontech 0:5868e8752d44 224 Q_SET_LENGTH(*q_ptr, len);
pythontech 0:5868e8752d44 225 return Q_GET_DATA(*q_ptr);
pythontech 0:5868e8752d44 226 }
pythontech 0:5868e8752d44 227
pythontech 0:5868e8752d44 228 qstr qstr_build_end(byte *q_ptr) {
pythontech 0:5868e8752d44 229 qstr q = qstr_find_strn((const char*)Q_GET_DATA(q_ptr), Q_GET_LENGTH(q_ptr));
pythontech 0:5868e8752d44 230 if (q == 0) {
pythontech 0:5868e8752d44 231 size_t len = Q_GET_LENGTH(q_ptr);
pythontech 0:5868e8752d44 232 mp_uint_t hash = qstr_compute_hash(Q_GET_DATA(q_ptr), len);
pythontech 0:5868e8752d44 233 Q_SET_HASH(q_ptr, hash);
pythontech 0:5868e8752d44 234 q_ptr[MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len] = '\0';
pythontech 0:5868e8752d44 235 q = qstr_add(q_ptr);
pythontech 0:5868e8752d44 236 } else {
pythontech 0:5868e8752d44 237 m_del(byte, q_ptr, Q_GET_ALLOC(q_ptr));
pythontech 0:5868e8752d44 238 }
pythontech 0:5868e8752d44 239 return q;
pythontech 0:5868e8752d44 240 }
pythontech 0:5868e8752d44 241
pythontech 0:5868e8752d44 242 mp_uint_t qstr_hash(qstr q) {
pythontech 0:5868e8752d44 243 return Q_GET_HASH(find_qstr(q));
pythontech 0:5868e8752d44 244 }
pythontech 0:5868e8752d44 245
pythontech 0:5868e8752d44 246 size_t qstr_len(qstr q) {
pythontech 0:5868e8752d44 247 const byte *qd = find_qstr(q);
pythontech 0:5868e8752d44 248 return Q_GET_LENGTH(qd);
pythontech 0:5868e8752d44 249 }
pythontech 0:5868e8752d44 250
pythontech 0:5868e8752d44 251 // XXX to remove!
pythontech 0:5868e8752d44 252 const char *qstr_str(qstr q) {
pythontech 0:5868e8752d44 253 const byte *qd = find_qstr(q);
pythontech 0:5868e8752d44 254 return (const char*)Q_GET_DATA(qd);
pythontech 0:5868e8752d44 255 }
pythontech 0:5868e8752d44 256
pythontech 0:5868e8752d44 257 const byte *qstr_data(qstr q, size_t *len) {
pythontech 0:5868e8752d44 258 const byte *qd = find_qstr(q);
pythontech 0:5868e8752d44 259 *len = Q_GET_LENGTH(qd);
pythontech 0:5868e8752d44 260 return Q_GET_DATA(qd);
pythontech 0:5868e8752d44 261 }
pythontech 0:5868e8752d44 262
pythontech 0:5868e8752d44 263 void qstr_pool_info(size_t *n_pool, size_t *n_qstr, size_t *n_str_data_bytes, size_t *n_total_bytes) {
pythontech 0:5868e8752d44 264 *n_pool = 0;
pythontech 0:5868e8752d44 265 *n_qstr = 0;
pythontech 0:5868e8752d44 266 *n_str_data_bytes = 0;
pythontech 0:5868e8752d44 267 *n_total_bytes = 0;
Colin Hogben 2:c89e95946844 268 for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL && pool != &CONST_POOL; pool = pool->prev) {
pythontech 0:5868e8752d44 269 *n_pool += 1;
pythontech 0:5868e8752d44 270 *n_qstr += pool->len;
pythontech 0:5868e8752d44 271 for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) {
pythontech 0:5868e8752d44 272 *n_str_data_bytes += Q_GET_ALLOC(*q);
pythontech 0:5868e8752d44 273 }
pythontech 0:5868e8752d44 274 #if MICROPY_ENABLE_GC
pythontech 0:5868e8752d44 275 *n_total_bytes += gc_nbytes(pool); // this counts actual bytes used in heap
pythontech 0:5868e8752d44 276 #else
pythontech 0:5868e8752d44 277 *n_total_bytes += sizeof(qstr_pool_t) + sizeof(qstr) * pool->alloc;
pythontech 0:5868e8752d44 278 #endif
pythontech 0:5868e8752d44 279 }
pythontech 0:5868e8752d44 280 *n_total_bytes += *n_str_data_bytes;
pythontech 0:5868e8752d44 281 }
pythontech 0:5868e8752d44 282
pythontech 0:5868e8752d44 283 #if MICROPY_PY_MICROPYTHON_MEM_INFO
pythontech 0:5868e8752d44 284 void qstr_dump_data(void) {
Colin Hogben 2:c89e95946844 285 for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL && pool != &CONST_POOL; pool = pool->prev) {
pythontech 0:5868e8752d44 286 for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) {
pythontech 0:5868e8752d44 287 mp_printf(&mp_plat_print, "Q(%s)\n", Q_GET_DATA(*q));
pythontech 0:5868e8752d44 288 }
pythontech 0:5868e8752d44 289 }
pythontech 0:5868e8752d44 290 }
pythontech 0:5868e8752d44 291 #endif