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 * Copyright (c) 2014 Paul Sokolovsky
pythontech 0:5868e8752d44 8 *
pythontech 0:5868e8752d44 9 * Permission is hereby granted, free of charge, to any person obtaining a copy
pythontech 0:5868e8752d44 10 * of this software and associated documentation files (the "Software"), to deal
pythontech 0:5868e8752d44 11 * in the Software without restriction, including without limitation the rights
pythontech 0:5868e8752d44 12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
pythontech 0:5868e8752d44 13 * copies of the Software, and to permit persons to whom the Software is
pythontech 0:5868e8752d44 14 * furnished to do so, subject to the following conditions:
pythontech 0:5868e8752d44 15 *
pythontech 0:5868e8752d44 16 * The above copyright notice and this permission notice shall be included in
pythontech 0:5868e8752d44 17 * all copies or substantial portions of the Software.
pythontech 0:5868e8752d44 18 *
pythontech 0:5868e8752d44 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
pythontech 0:5868e8752d44 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
pythontech 0:5868e8752d44 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
pythontech 0:5868e8752d44 22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
pythontech 0:5868e8752d44 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
pythontech 0:5868e8752d44 24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
pythontech 0:5868e8752d44 25 * THE SOFTWARE.
pythontech 0:5868e8752d44 26 */
pythontech 0:5868e8752d44 27
pythontech 0:5868e8752d44 28 #include <stdio.h>
pythontech 0:5868e8752d44 29 #include <string.h>
pythontech 0:5868e8752d44 30 #include <assert.h>
pythontech 0:5868e8752d44 31
pythontech 0:5868e8752d44 32 #include "py/mpstate.h"
pythontech 0:5868e8752d44 33 #include "py/nlr.h"
pythontech 0:5868e8752d44 34 #include "py/emitglue.h"
pythontech 0:5868e8752d44 35 #include "py/objtype.h"
pythontech 0:5868e8752d44 36 #include "py/runtime.h"
pythontech 0:5868e8752d44 37 #include "py/bc0.h"
pythontech 0:5868e8752d44 38 #include "py/bc.h"
pythontech 0:5868e8752d44 39
pythontech 0:5868e8752d44 40 #if 0
pythontech 0:5868e8752d44 41 //#define TRACE(ip) printf("sp=" INT_FMT " ", sp - code_state->sp); mp_bytecode_print2(ip, 1);
pythontech 0:5868e8752d44 42 #define TRACE(ip) printf("sp=%d ", sp - code_state->sp); mp_bytecode_print2(ip, 1);
pythontech 0:5868e8752d44 43 #else
pythontech 0:5868e8752d44 44 #define TRACE(ip)
pythontech 0:5868e8752d44 45 #endif
pythontech 0:5868e8752d44 46
pythontech 0:5868e8752d44 47 // Value stack grows up (this makes it incompatible with native C stack, but
pythontech 0:5868e8752d44 48 // makes sure that arguments to functions are in natural order arg1..argN
pythontech 0:5868e8752d44 49 // (Python semantics mandates left-to-right evaluation order, including for
pythontech 0:5868e8752d44 50 // function arguments). Stack pointer is pre-incremented and points at the
pythontech 0:5868e8752d44 51 // top element.
pythontech 0:5868e8752d44 52 // Exception stack also grows up, top element is also pointed at.
pythontech 0:5868e8752d44 53
pythontech 0:5868e8752d44 54 // Exception stack unwind reasons (WHY_* in CPython-speak)
pythontech 0:5868e8752d44 55 // TODO perhaps compress this to RETURN=0, JUMP>0, with number of unwinds
pythontech 0:5868e8752d44 56 // left to do encoded in the JUMP number
pythontech 0:5868e8752d44 57 typedef enum {
pythontech 0:5868e8752d44 58 UNWIND_RETURN = 1,
pythontech 0:5868e8752d44 59 UNWIND_JUMP,
pythontech 0:5868e8752d44 60 } mp_unwind_reason_t;
pythontech 0:5868e8752d44 61
pythontech 0:5868e8752d44 62 #define DECODE_UINT \
pythontech 0:5868e8752d44 63 mp_uint_t unum = 0; \
pythontech 0:5868e8752d44 64 do { \
pythontech 0:5868e8752d44 65 unum = (unum << 7) + (*ip & 0x7f); \
pythontech 0:5868e8752d44 66 } while ((*ip++ & 0x80) != 0)
pythontech 0:5868e8752d44 67 #define DECODE_ULABEL mp_uint_t ulab = (ip[0] | (ip[1] << 8)); ip += 2
pythontech 0:5868e8752d44 68 #define DECODE_SLABEL mp_uint_t slab = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2
pythontech 0:5868e8752d44 69
pythontech 0:5868e8752d44 70 #if MICROPY_PERSISTENT_CODE
pythontech 0:5868e8752d44 71
pythontech 0:5868e8752d44 72 #define DECODE_QSTR \
pythontech 0:5868e8752d44 73 qstr qst = ip[0] | ip[1] << 8; \
pythontech 0:5868e8752d44 74 ip += 2;
pythontech 0:5868e8752d44 75 #define DECODE_PTR \
pythontech 0:5868e8752d44 76 DECODE_UINT; \
pythontech 0:5868e8752d44 77 void *ptr = (void*)(uintptr_t)code_state->const_table[unum]
pythontech 0:5868e8752d44 78 #define DECODE_OBJ \
pythontech 0:5868e8752d44 79 DECODE_UINT; \
pythontech 0:5868e8752d44 80 mp_obj_t obj = (mp_obj_t)code_state->const_table[unum]
pythontech 0:5868e8752d44 81
pythontech 0:5868e8752d44 82 #else
pythontech 0:5868e8752d44 83
pythontech 0:5868e8752d44 84 #define DECODE_QSTR qstr qst = 0; \
pythontech 0:5868e8752d44 85 do { \
pythontech 0:5868e8752d44 86 qst = (qst << 7) + (*ip & 0x7f); \
pythontech 0:5868e8752d44 87 } while ((*ip++ & 0x80) != 0)
pythontech 0:5868e8752d44 88 #define DECODE_PTR \
pythontech 0:5868e8752d44 89 ip = (byte*)MP_ALIGN(ip, sizeof(void*)); \
pythontech 0:5868e8752d44 90 void *ptr = *(void**)ip; \
pythontech 0:5868e8752d44 91 ip += sizeof(void*)
pythontech 0:5868e8752d44 92 #define DECODE_OBJ \
pythontech 0:5868e8752d44 93 ip = (byte*)MP_ALIGN(ip, sizeof(mp_obj_t)); \
pythontech 0:5868e8752d44 94 mp_obj_t obj = *(mp_obj_t*)ip; \
pythontech 0:5868e8752d44 95 ip += sizeof(mp_obj_t)
pythontech 0:5868e8752d44 96
pythontech 0:5868e8752d44 97 #endif
pythontech 0:5868e8752d44 98
pythontech 0:5868e8752d44 99 #define PUSH(val) *++sp = (val)
pythontech 0:5868e8752d44 100 #define POP() (*sp--)
pythontech 0:5868e8752d44 101 #define TOP() (*sp)
pythontech 0:5868e8752d44 102 #define SET_TOP(val) *sp = (val)
pythontech 0:5868e8752d44 103
pythontech 0:5868e8752d44 104 #if MICROPY_PY_SYS_EXC_INFO
pythontech 0:5868e8752d44 105 #define CLEAR_SYS_EXC_INFO() MP_STATE_VM(cur_exception) = NULL;
pythontech 0:5868e8752d44 106 #else
pythontech 0:5868e8752d44 107 #define CLEAR_SYS_EXC_INFO()
pythontech 0:5868e8752d44 108 #endif
pythontech 0:5868e8752d44 109
pythontech 0:5868e8752d44 110 #define PUSH_EXC_BLOCK(with_or_finally) do { \
pythontech 0:5868e8752d44 111 DECODE_ULABEL; /* except labels are always forward */ \
pythontech 0:5868e8752d44 112 ++exc_sp; \
pythontech 0:5868e8752d44 113 exc_sp->handler = ip + ulab; \
pythontech 0:5868e8752d44 114 exc_sp->val_sp = MP_TAGPTR_MAKE(sp, ((with_or_finally) << 1) | currently_in_except_block); \
pythontech 0:5868e8752d44 115 exc_sp->prev_exc = NULL; \
pythontech 0:5868e8752d44 116 currently_in_except_block = 0; /* in a try block now */ \
pythontech 0:5868e8752d44 117 } while (0)
pythontech 0:5868e8752d44 118
pythontech 0:5868e8752d44 119 #define POP_EXC_BLOCK() \
pythontech 0:5868e8752d44 120 currently_in_except_block = MP_TAGPTR_TAG0(exc_sp->val_sp); /* restore previous state */ \
pythontech 0:5868e8752d44 121 exc_sp--; /* pop back to previous exception handler */ \
pythontech 0:5868e8752d44 122 CLEAR_SYS_EXC_INFO() /* just clear sys.exc_info(), not compliant, but it shouldn't be used in 1st place */
pythontech 0:5868e8752d44 123
pythontech 0:5868e8752d44 124 // fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)
pythontech 0:5868e8752d44 125 // sp points to bottom of stack which grows up
pythontech 0:5868e8752d44 126 // returns:
pythontech 0:5868e8752d44 127 // MP_VM_RETURN_NORMAL, sp valid, return value in *sp
pythontech 0:5868e8752d44 128 // MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
pythontech 0:5868e8752d44 129 // MP_VM_RETURN_EXCEPTION, exception in fastn[0]
pythontech 0:5868e8752d44 130 mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_obj_t inject_exc) {
pythontech 0:5868e8752d44 131 #define SELECTIVE_EXC_IP (0)
pythontech 0:5868e8752d44 132 #if SELECTIVE_EXC_IP
pythontech 0:5868e8752d44 133 #define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */
pythontech 0:5868e8752d44 134 #define MARK_EXC_IP_GLOBAL()
pythontech 0:5868e8752d44 135 #else
pythontech 0:5868e8752d44 136 #define MARK_EXC_IP_SELECTIVE()
pythontech 0:5868e8752d44 137 #define MARK_EXC_IP_GLOBAL() { code_state->ip = ip; } /* stores ip pointing to last opcode */
pythontech 0:5868e8752d44 138 #endif
pythontech 0:5868e8752d44 139 #if MICROPY_OPT_COMPUTED_GOTO
pythontech 0:5868e8752d44 140 #include "py/vmentrytable.h"
pythontech 0:5868e8752d44 141 #define DISPATCH() do { \
pythontech 0:5868e8752d44 142 TRACE(ip); \
pythontech 0:5868e8752d44 143 MARK_EXC_IP_GLOBAL(); \
pythontech 0:5868e8752d44 144 goto *entry_table[*ip++]; \
pythontech 0:5868e8752d44 145 } while (0)
pythontech 0:5868e8752d44 146 #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
pythontech 0:5868e8752d44 147 #define ENTRY(op) entry_##op
pythontech 0:5868e8752d44 148 #define ENTRY_DEFAULT entry_default
pythontech 0:5868e8752d44 149 #else
pythontech 0:5868e8752d44 150 #define DISPATCH() break
pythontech 0:5868e8752d44 151 #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
pythontech 0:5868e8752d44 152 #define ENTRY(op) case op
pythontech 0:5868e8752d44 153 #define ENTRY_DEFAULT default
pythontech 0:5868e8752d44 154 #endif
pythontech 0:5868e8752d44 155
pythontech 0:5868e8752d44 156 // nlr_raise needs to be implemented as a goto, so that the C compiler's flow analyser
pythontech 0:5868e8752d44 157 // sees that it's possible for us to jump from the dispatch loop to the exception
pythontech 0:5868e8752d44 158 // handler. Without this, the code may have a different stack layout in the dispatch
pythontech 0:5868e8752d44 159 // loop and the exception handler, leading to very obscure bugs.
pythontech 0:5868e8752d44 160 #define RAISE(o) do { nlr_pop(); nlr.ret_val = MP_OBJ_TO_PTR(o); goto exception_handler; } while (0)
pythontech 0:5868e8752d44 161
pythontech 0:5868e8752d44 162 #if MICROPY_STACKLESS
pythontech 0:5868e8752d44 163 run_code_state: ;
pythontech 0:5868e8752d44 164 #endif
pythontech 0:5868e8752d44 165 // Pointers which are constant for particular invocation of mp_execute_bytecode()
pythontech 0:5868e8752d44 166 mp_obj_t * /*const*/ fastn = &code_state->state[code_state->n_state - 1];
pythontech 0:5868e8752d44 167 mp_exc_stack_t * /*const*/ exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
pythontech 0:5868e8752d44 168
pythontech 0:5868e8752d44 169 // variables that are visible to the exception handler (declared volatile)
pythontech 0:5868e8752d44 170 volatile bool currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
pythontech 0:5868e8752d44 171 mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
pythontech 0:5868e8752d44 172
pythontech 0:5868e8752d44 173 // outer exception handling loop
pythontech 0:5868e8752d44 174 for (;;) {
pythontech 0:5868e8752d44 175 nlr_buf_t nlr;
pythontech 0:5868e8752d44 176 outer_dispatch_loop:
pythontech 0:5868e8752d44 177 if (nlr_push(&nlr) == 0) {
pythontech 0:5868e8752d44 178 // local variables that are not visible to the exception handler
pythontech 0:5868e8752d44 179 const byte *ip = code_state->ip;
pythontech 0:5868e8752d44 180 mp_obj_t *sp = code_state->sp;
pythontech 0:5868e8752d44 181 mp_obj_t obj_shared;
pythontech 0:5868e8752d44 182 MICROPY_VM_HOOK_INIT
pythontech 0:5868e8752d44 183
pythontech 0:5868e8752d44 184 // If we have exception to inject, now that we finish setting up
pythontech 0:5868e8752d44 185 // execution context, raise it. This works as if RAISE_VARARGS
pythontech 0:5868e8752d44 186 // bytecode was executed.
pythontech 0:5868e8752d44 187 // Injecting exc into yield from generator is a special case,
pythontech 0:5868e8752d44 188 // handled by MP_BC_YIELD_FROM itself
pythontech 0:5868e8752d44 189 if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
pythontech 0:5868e8752d44 190 mp_obj_t exc = inject_exc;
pythontech 0:5868e8752d44 191 inject_exc = MP_OBJ_NULL;
pythontech 0:5868e8752d44 192 exc = mp_make_raise_obj(exc);
pythontech 0:5868e8752d44 193 RAISE(exc);
pythontech 0:5868e8752d44 194 }
pythontech 0:5868e8752d44 195
pythontech 0:5868e8752d44 196 // loop to execute byte code
pythontech 0:5868e8752d44 197 for (;;) {
pythontech 0:5868e8752d44 198 dispatch_loop:
pythontech 0:5868e8752d44 199 #if MICROPY_OPT_COMPUTED_GOTO
pythontech 0:5868e8752d44 200 DISPATCH();
pythontech 0:5868e8752d44 201 #else
pythontech 0:5868e8752d44 202 TRACE(ip);
pythontech 0:5868e8752d44 203 MARK_EXC_IP_GLOBAL();
pythontech 0:5868e8752d44 204 switch (*ip++) {
pythontech 0:5868e8752d44 205 #endif
pythontech 0:5868e8752d44 206
pythontech 0:5868e8752d44 207 ENTRY(MP_BC_LOAD_CONST_FALSE):
pythontech 0:5868e8752d44 208 PUSH(mp_const_false);
pythontech 0:5868e8752d44 209 DISPATCH();
pythontech 0:5868e8752d44 210
pythontech 0:5868e8752d44 211 ENTRY(MP_BC_LOAD_CONST_NONE):
pythontech 0:5868e8752d44 212 PUSH(mp_const_none);
pythontech 0:5868e8752d44 213 DISPATCH();
pythontech 0:5868e8752d44 214
pythontech 0:5868e8752d44 215 ENTRY(MP_BC_LOAD_CONST_TRUE):
pythontech 0:5868e8752d44 216 PUSH(mp_const_true);
pythontech 0:5868e8752d44 217 DISPATCH();
pythontech 0:5868e8752d44 218
pythontech 0:5868e8752d44 219 ENTRY(MP_BC_LOAD_CONST_SMALL_INT): {
pythontech 0:5868e8752d44 220 mp_int_t num = 0;
pythontech 0:5868e8752d44 221 if ((ip[0] & 0x40) != 0) {
pythontech 0:5868e8752d44 222 // Number is negative
pythontech 0:5868e8752d44 223 num--;
pythontech 0:5868e8752d44 224 }
pythontech 0:5868e8752d44 225 do {
pythontech 0:5868e8752d44 226 num = (num << 7) | (*ip & 0x7f);
pythontech 0:5868e8752d44 227 } while ((*ip++ & 0x80) != 0);
pythontech 0:5868e8752d44 228 PUSH(MP_OBJ_NEW_SMALL_INT(num));
pythontech 0:5868e8752d44 229 DISPATCH();
pythontech 0:5868e8752d44 230 }
pythontech 0:5868e8752d44 231
pythontech 0:5868e8752d44 232 ENTRY(MP_BC_LOAD_CONST_STRING): {
pythontech 0:5868e8752d44 233 DECODE_QSTR;
pythontech 0:5868e8752d44 234 PUSH(MP_OBJ_NEW_QSTR(qst));
pythontech 0:5868e8752d44 235 DISPATCH();
pythontech 0:5868e8752d44 236 }
pythontech 0:5868e8752d44 237
pythontech 0:5868e8752d44 238 ENTRY(MP_BC_LOAD_CONST_OBJ): {
pythontech 0:5868e8752d44 239 DECODE_OBJ;
pythontech 0:5868e8752d44 240 PUSH(obj);
pythontech 0:5868e8752d44 241 DISPATCH();
pythontech 0:5868e8752d44 242 }
pythontech 0:5868e8752d44 243
pythontech 0:5868e8752d44 244 ENTRY(MP_BC_LOAD_NULL):
pythontech 0:5868e8752d44 245 PUSH(MP_OBJ_NULL);
pythontech 0:5868e8752d44 246 DISPATCH();
pythontech 0:5868e8752d44 247
pythontech 0:5868e8752d44 248 ENTRY(MP_BC_LOAD_FAST_N): {
pythontech 0:5868e8752d44 249 DECODE_UINT;
pythontech 0:5868e8752d44 250 obj_shared = fastn[-unum];
pythontech 0:5868e8752d44 251 load_check:
pythontech 0:5868e8752d44 252 if (obj_shared == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 253 local_name_error: {
pythontech 0:5868e8752d44 254 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 255 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment");
pythontech 0:5868e8752d44 256 RAISE(obj);
pythontech 0:5868e8752d44 257 }
pythontech 0:5868e8752d44 258 }
pythontech 0:5868e8752d44 259 PUSH(obj_shared);
pythontech 0:5868e8752d44 260 DISPATCH();
pythontech 0:5868e8752d44 261 }
pythontech 0:5868e8752d44 262
pythontech 0:5868e8752d44 263 ENTRY(MP_BC_LOAD_DEREF): {
pythontech 0:5868e8752d44 264 DECODE_UINT;
pythontech 0:5868e8752d44 265 obj_shared = mp_obj_cell_get(fastn[-unum]);
pythontech 0:5868e8752d44 266 goto load_check;
pythontech 0:5868e8752d44 267 }
pythontech 0:5868e8752d44 268
pythontech 0:5868e8752d44 269 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
pythontech 0:5868e8752d44 270 ENTRY(MP_BC_LOAD_NAME): {
pythontech 0:5868e8752d44 271 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 272 DECODE_QSTR;
pythontech 0:5868e8752d44 273 PUSH(mp_load_name(qst));
pythontech 0:5868e8752d44 274 DISPATCH();
pythontech 0:5868e8752d44 275 }
pythontech 0:5868e8752d44 276 #else
pythontech 0:5868e8752d44 277 ENTRY(MP_BC_LOAD_NAME): {
pythontech 0:5868e8752d44 278 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 279 DECODE_QSTR;
pythontech 0:5868e8752d44 280 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
pythontech 0:5868e8752d44 281 mp_uint_t x = *ip;
pythontech 0:5868e8752d44 282 if (x < MP_STATE_CTX(dict_locals)->map.alloc && MP_STATE_CTX(dict_locals)->map.table[x].key == key) {
pythontech 0:5868e8752d44 283 PUSH(MP_STATE_CTX(dict_locals)->map.table[x].value);
pythontech 0:5868e8752d44 284 } else {
pythontech 0:5868e8752d44 285 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_locals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
pythontech 0:5868e8752d44 286 if (elem != NULL) {
pythontech 0:5868e8752d44 287 *(byte*)ip = (elem - &MP_STATE_CTX(dict_locals)->map.table[0]) & 0xff;
pythontech 0:5868e8752d44 288 PUSH(elem->value);
pythontech 0:5868e8752d44 289 } else {
pythontech 0:5868e8752d44 290 PUSH(mp_load_name(MP_OBJ_QSTR_VALUE(key)));
pythontech 0:5868e8752d44 291 }
pythontech 0:5868e8752d44 292 }
pythontech 0:5868e8752d44 293 ip++;
pythontech 0:5868e8752d44 294 DISPATCH();
pythontech 0:5868e8752d44 295 }
pythontech 0:5868e8752d44 296 #endif
pythontech 0:5868e8752d44 297
pythontech 0:5868e8752d44 298 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
pythontech 0:5868e8752d44 299 ENTRY(MP_BC_LOAD_GLOBAL): {
pythontech 0:5868e8752d44 300 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 301 DECODE_QSTR;
pythontech 0:5868e8752d44 302 PUSH(mp_load_global(qst));
pythontech 0:5868e8752d44 303 DISPATCH();
pythontech 0:5868e8752d44 304 }
pythontech 0:5868e8752d44 305 #else
pythontech 0:5868e8752d44 306 ENTRY(MP_BC_LOAD_GLOBAL): {
pythontech 0:5868e8752d44 307 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 308 DECODE_QSTR;
pythontech 0:5868e8752d44 309 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
pythontech 0:5868e8752d44 310 mp_uint_t x = *ip;
pythontech 0:5868e8752d44 311 if (x < MP_STATE_CTX(dict_globals)->map.alloc && MP_STATE_CTX(dict_globals)->map.table[x].key == key) {
pythontech 0:5868e8752d44 312 PUSH(MP_STATE_CTX(dict_globals)->map.table[x].value);
pythontech 0:5868e8752d44 313 } else {
pythontech 0:5868e8752d44 314 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_globals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
pythontech 0:5868e8752d44 315 if (elem != NULL) {
pythontech 0:5868e8752d44 316 *(byte*)ip = (elem - &MP_STATE_CTX(dict_globals)->map.table[0]) & 0xff;
pythontech 0:5868e8752d44 317 PUSH(elem->value);
pythontech 0:5868e8752d44 318 } else {
pythontech 0:5868e8752d44 319 PUSH(mp_load_global(MP_OBJ_QSTR_VALUE(key)));
pythontech 0:5868e8752d44 320 }
pythontech 0:5868e8752d44 321 }
pythontech 0:5868e8752d44 322 ip++;
pythontech 0:5868e8752d44 323 DISPATCH();
pythontech 0:5868e8752d44 324 }
pythontech 0:5868e8752d44 325 #endif
pythontech 0:5868e8752d44 326
pythontech 0:5868e8752d44 327 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
pythontech 0:5868e8752d44 328 ENTRY(MP_BC_LOAD_ATTR): {
pythontech 0:5868e8752d44 329 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 330 DECODE_QSTR;
pythontech 0:5868e8752d44 331 SET_TOP(mp_load_attr(TOP(), qst));
pythontech 0:5868e8752d44 332 DISPATCH();
pythontech 0:5868e8752d44 333 }
pythontech 0:5868e8752d44 334 #else
pythontech 0:5868e8752d44 335 ENTRY(MP_BC_LOAD_ATTR): {
pythontech 0:5868e8752d44 336 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 337 DECODE_QSTR;
pythontech 0:5868e8752d44 338 mp_obj_t top = TOP();
pythontech 0:5868e8752d44 339 if (mp_obj_get_type(top)->attr == mp_obj_instance_attr) {
pythontech 0:5868e8752d44 340 mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
pythontech 0:5868e8752d44 341 mp_uint_t x = *ip;
pythontech 0:5868e8752d44 342 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
pythontech 0:5868e8752d44 343 mp_map_elem_t *elem;
pythontech 0:5868e8752d44 344 if (x < self->members.alloc && self->members.table[x].key == key) {
pythontech 0:5868e8752d44 345 elem = &self->members.table[x];
pythontech 0:5868e8752d44 346 } else {
pythontech 0:5868e8752d44 347 elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);
pythontech 0:5868e8752d44 348 if (elem != NULL) {
pythontech 0:5868e8752d44 349 *(byte*)ip = elem - &self->members.table[0];
pythontech 0:5868e8752d44 350 } else {
pythontech 0:5868e8752d44 351 goto load_attr_cache_fail;
pythontech 0:5868e8752d44 352 }
pythontech 0:5868e8752d44 353 }
pythontech 0:5868e8752d44 354 SET_TOP(elem->value);
pythontech 0:5868e8752d44 355 ip++;
pythontech 0:5868e8752d44 356 DISPATCH();
pythontech 0:5868e8752d44 357 }
pythontech 0:5868e8752d44 358 load_attr_cache_fail:
pythontech 0:5868e8752d44 359 SET_TOP(mp_load_attr(top, qst));
pythontech 0:5868e8752d44 360 ip++;
pythontech 0:5868e8752d44 361 DISPATCH();
pythontech 0:5868e8752d44 362 }
pythontech 0:5868e8752d44 363 #endif
pythontech 0:5868e8752d44 364
pythontech 0:5868e8752d44 365 ENTRY(MP_BC_LOAD_METHOD): {
pythontech 0:5868e8752d44 366 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 367 DECODE_QSTR;
pythontech 0:5868e8752d44 368 mp_load_method(*sp, qst, sp);
pythontech 0:5868e8752d44 369 sp += 1;
pythontech 0:5868e8752d44 370 DISPATCH();
pythontech 0:5868e8752d44 371 }
pythontech 0:5868e8752d44 372
pythontech 0:5868e8752d44 373 ENTRY(MP_BC_LOAD_BUILD_CLASS):
pythontech 0:5868e8752d44 374 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 375 PUSH(mp_load_build_class());
pythontech 0:5868e8752d44 376 DISPATCH();
pythontech 0:5868e8752d44 377
pythontech 0:5868e8752d44 378 ENTRY(MP_BC_LOAD_SUBSCR): {
pythontech 0:5868e8752d44 379 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 380 mp_obj_t index = POP();
pythontech 0:5868e8752d44 381 SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL));
pythontech 0:5868e8752d44 382 DISPATCH();
pythontech 0:5868e8752d44 383 }
pythontech 0:5868e8752d44 384
pythontech 0:5868e8752d44 385 ENTRY(MP_BC_STORE_FAST_N): {
pythontech 0:5868e8752d44 386 DECODE_UINT;
pythontech 0:5868e8752d44 387 fastn[-unum] = POP();
pythontech 0:5868e8752d44 388 DISPATCH();
pythontech 0:5868e8752d44 389 }
pythontech 0:5868e8752d44 390
pythontech 0:5868e8752d44 391 ENTRY(MP_BC_STORE_DEREF): {
pythontech 0:5868e8752d44 392 DECODE_UINT;
pythontech 0:5868e8752d44 393 mp_obj_cell_set(fastn[-unum], POP());
pythontech 0:5868e8752d44 394 DISPATCH();
pythontech 0:5868e8752d44 395 }
pythontech 0:5868e8752d44 396
pythontech 0:5868e8752d44 397 ENTRY(MP_BC_STORE_NAME): {
pythontech 0:5868e8752d44 398 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 399 DECODE_QSTR;
pythontech 0:5868e8752d44 400 mp_store_name(qst, POP());
pythontech 0:5868e8752d44 401 DISPATCH();
pythontech 0:5868e8752d44 402 }
pythontech 0:5868e8752d44 403
pythontech 0:5868e8752d44 404 ENTRY(MP_BC_STORE_GLOBAL): {
pythontech 0:5868e8752d44 405 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 406 DECODE_QSTR;
pythontech 0:5868e8752d44 407 mp_store_global(qst, POP());
pythontech 0:5868e8752d44 408 DISPATCH();
pythontech 0:5868e8752d44 409 }
pythontech 0:5868e8752d44 410
pythontech 0:5868e8752d44 411 #if !MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE
pythontech 0:5868e8752d44 412 ENTRY(MP_BC_STORE_ATTR): {
pythontech 0:5868e8752d44 413 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 414 DECODE_QSTR;
pythontech 0:5868e8752d44 415 mp_store_attr(sp[0], qst, sp[-1]);
pythontech 0:5868e8752d44 416 sp -= 2;
pythontech 0:5868e8752d44 417 DISPATCH();
pythontech 0:5868e8752d44 418 }
pythontech 0:5868e8752d44 419 #else
pythontech 0:5868e8752d44 420 // This caching code works with MICROPY_PY_BUILTINS_PROPERTY and/or
pythontech 0:5868e8752d44 421 // MICROPY_PY_DESCRIPTORS enabled because if the attr exists in
pythontech 0:5868e8752d44 422 // self->members then it can't be a property or have descriptors. A
pythontech 0:5868e8752d44 423 // consequence of this is that we can't use MP_MAP_LOOKUP_ADD_IF_NOT_FOUND
pythontech 0:5868e8752d44 424 // in the fast-path below, because that store could override a property.
pythontech 0:5868e8752d44 425 ENTRY(MP_BC_STORE_ATTR): {
pythontech 0:5868e8752d44 426 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 427 DECODE_QSTR;
pythontech 0:5868e8752d44 428 mp_obj_t top = TOP();
pythontech 0:5868e8752d44 429 if (mp_obj_get_type(top)->attr == mp_obj_instance_attr && sp[-1] != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 430 mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
pythontech 0:5868e8752d44 431 mp_uint_t x = *ip;
pythontech 0:5868e8752d44 432 mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
pythontech 0:5868e8752d44 433 mp_map_elem_t *elem;
pythontech 0:5868e8752d44 434 if (x < self->members.alloc && self->members.table[x].key == key) {
pythontech 0:5868e8752d44 435 elem = &self->members.table[x];
pythontech 0:5868e8752d44 436 } else {
pythontech 0:5868e8752d44 437 elem = mp_map_lookup(&self->members, key, MP_MAP_LOOKUP);
pythontech 0:5868e8752d44 438 if (elem != NULL) {
pythontech 0:5868e8752d44 439 *(byte*)ip = elem - &self->members.table[0];
pythontech 0:5868e8752d44 440 } else {
pythontech 0:5868e8752d44 441 goto store_attr_cache_fail;
pythontech 0:5868e8752d44 442 }
pythontech 0:5868e8752d44 443 }
pythontech 0:5868e8752d44 444 elem->value = sp[-1];
pythontech 0:5868e8752d44 445 sp -= 2;
pythontech 0:5868e8752d44 446 ip++;
pythontech 0:5868e8752d44 447 DISPATCH();
pythontech 0:5868e8752d44 448 }
pythontech 0:5868e8752d44 449 store_attr_cache_fail:
pythontech 0:5868e8752d44 450 mp_store_attr(sp[0], qst, sp[-1]);
pythontech 0:5868e8752d44 451 sp -= 2;
pythontech 0:5868e8752d44 452 ip++;
pythontech 0:5868e8752d44 453 DISPATCH();
pythontech 0:5868e8752d44 454 }
pythontech 0:5868e8752d44 455 #endif
pythontech 0:5868e8752d44 456
pythontech 0:5868e8752d44 457 ENTRY(MP_BC_STORE_SUBSCR):
pythontech 0:5868e8752d44 458 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 459 mp_obj_subscr(sp[-1], sp[0], sp[-2]);
pythontech 0:5868e8752d44 460 sp -= 3;
pythontech 0:5868e8752d44 461 DISPATCH();
pythontech 0:5868e8752d44 462
pythontech 0:5868e8752d44 463 ENTRY(MP_BC_DELETE_FAST): {
pythontech 0:5868e8752d44 464 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 465 DECODE_UINT;
pythontech 0:5868e8752d44 466 if (fastn[-unum] == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 467 goto local_name_error;
pythontech 0:5868e8752d44 468 }
pythontech 0:5868e8752d44 469 fastn[-unum] = MP_OBJ_NULL;
pythontech 0:5868e8752d44 470 DISPATCH();
pythontech 0:5868e8752d44 471 }
pythontech 0:5868e8752d44 472
pythontech 0:5868e8752d44 473 ENTRY(MP_BC_DELETE_DEREF): {
pythontech 0:5868e8752d44 474 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 475 DECODE_UINT;
pythontech 0:5868e8752d44 476 if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 477 goto local_name_error;
pythontech 0:5868e8752d44 478 }
pythontech 0:5868e8752d44 479 mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);
pythontech 0:5868e8752d44 480 DISPATCH();
pythontech 0:5868e8752d44 481 }
pythontech 0:5868e8752d44 482
pythontech 0:5868e8752d44 483 ENTRY(MP_BC_DELETE_NAME): {
pythontech 0:5868e8752d44 484 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 485 DECODE_QSTR;
pythontech 0:5868e8752d44 486 mp_delete_name(qst);
pythontech 0:5868e8752d44 487 DISPATCH();
pythontech 0:5868e8752d44 488 }
pythontech 0:5868e8752d44 489
pythontech 0:5868e8752d44 490 ENTRY(MP_BC_DELETE_GLOBAL): {
pythontech 0:5868e8752d44 491 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 492 DECODE_QSTR;
pythontech 0:5868e8752d44 493 mp_delete_global(qst);
pythontech 0:5868e8752d44 494 DISPATCH();
pythontech 0:5868e8752d44 495 }
pythontech 0:5868e8752d44 496
pythontech 0:5868e8752d44 497 ENTRY(MP_BC_DUP_TOP): {
pythontech 0:5868e8752d44 498 mp_obj_t top = TOP();
pythontech 0:5868e8752d44 499 PUSH(top);
pythontech 0:5868e8752d44 500 DISPATCH();
pythontech 0:5868e8752d44 501 }
pythontech 0:5868e8752d44 502
pythontech 0:5868e8752d44 503 ENTRY(MP_BC_DUP_TOP_TWO):
pythontech 0:5868e8752d44 504 sp += 2;
pythontech 0:5868e8752d44 505 sp[0] = sp[-2];
pythontech 0:5868e8752d44 506 sp[-1] = sp[-3];
pythontech 0:5868e8752d44 507 DISPATCH();
pythontech 0:5868e8752d44 508
pythontech 0:5868e8752d44 509 ENTRY(MP_BC_POP_TOP):
pythontech 0:5868e8752d44 510 sp -= 1;
pythontech 0:5868e8752d44 511 DISPATCH();
pythontech 0:5868e8752d44 512
pythontech 0:5868e8752d44 513 ENTRY(MP_BC_ROT_TWO): {
pythontech 0:5868e8752d44 514 mp_obj_t top = sp[0];
pythontech 0:5868e8752d44 515 sp[0] = sp[-1];
pythontech 0:5868e8752d44 516 sp[-1] = top;
pythontech 0:5868e8752d44 517 DISPATCH();
pythontech 0:5868e8752d44 518 }
pythontech 0:5868e8752d44 519
pythontech 0:5868e8752d44 520 ENTRY(MP_BC_ROT_THREE): {
pythontech 0:5868e8752d44 521 mp_obj_t top = sp[0];
pythontech 0:5868e8752d44 522 sp[0] = sp[-1];
pythontech 0:5868e8752d44 523 sp[-1] = sp[-2];
pythontech 0:5868e8752d44 524 sp[-2] = top;
pythontech 0:5868e8752d44 525 DISPATCH();
pythontech 0:5868e8752d44 526 }
pythontech 0:5868e8752d44 527
pythontech 0:5868e8752d44 528 ENTRY(MP_BC_JUMP): {
pythontech 0:5868e8752d44 529 DECODE_SLABEL;
pythontech 0:5868e8752d44 530 ip += slab;
pythontech 0:5868e8752d44 531 DISPATCH_WITH_PEND_EXC_CHECK();
pythontech 0:5868e8752d44 532 }
pythontech 0:5868e8752d44 533
pythontech 0:5868e8752d44 534 ENTRY(MP_BC_POP_JUMP_IF_TRUE): {
pythontech 0:5868e8752d44 535 DECODE_SLABEL;
pythontech 0:5868e8752d44 536 if (mp_obj_is_true(POP())) {
pythontech 0:5868e8752d44 537 ip += slab;
pythontech 0:5868e8752d44 538 }
pythontech 0:5868e8752d44 539 DISPATCH_WITH_PEND_EXC_CHECK();
pythontech 0:5868e8752d44 540 }
pythontech 0:5868e8752d44 541
pythontech 0:5868e8752d44 542 ENTRY(MP_BC_POP_JUMP_IF_FALSE): {
pythontech 0:5868e8752d44 543 DECODE_SLABEL;
pythontech 0:5868e8752d44 544 if (!mp_obj_is_true(POP())) {
pythontech 0:5868e8752d44 545 ip += slab;
pythontech 0:5868e8752d44 546 }
pythontech 0:5868e8752d44 547 DISPATCH_WITH_PEND_EXC_CHECK();
pythontech 0:5868e8752d44 548 }
pythontech 0:5868e8752d44 549
pythontech 0:5868e8752d44 550 ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP): {
pythontech 0:5868e8752d44 551 DECODE_SLABEL;
pythontech 0:5868e8752d44 552 if (mp_obj_is_true(TOP())) {
pythontech 0:5868e8752d44 553 ip += slab;
pythontech 0:5868e8752d44 554 } else {
pythontech 0:5868e8752d44 555 sp--;
pythontech 0:5868e8752d44 556 }
pythontech 0:5868e8752d44 557 DISPATCH_WITH_PEND_EXC_CHECK();
pythontech 0:5868e8752d44 558 }
pythontech 0:5868e8752d44 559
pythontech 0:5868e8752d44 560 ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP): {
pythontech 0:5868e8752d44 561 DECODE_SLABEL;
pythontech 0:5868e8752d44 562 if (mp_obj_is_true(TOP())) {
pythontech 0:5868e8752d44 563 sp--;
pythontech 0:5868e8752d44 564 } else {
pythontech 0:5868e8752d44 565 ip += slab;
pythontech 0:5868e8752d44 566 }
pythontech 0:5868e8752d44 567 DISPATCH_WITH_PEND_EXC_CHECK();
pythontech 0:5868e8752d44 568 }
pythontech 0:5868e8752d44 569
pythontech 0:5868e8752d44 570 ENTRY(MP_BC_SETUP_WITH): {
pythontech 0:5868e8752d44 571 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 572 // stack: (..., ctx_mgr)
pythontech 0:5868e8752d44 573 mp_obj_t obj = TOP();
pythontech 0:5868e8752d44 574 mp_load_method(obj, MP_QSTR___exit__, sp);
pythontech 0:5868e8752d44 575 mp_load_method(obj, MP_QSTR___enter__, sp + 2);
pythontech 0:5868e8752d44 576 mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 2);
pythontech 0:5868e8752d44 577 sp += 1;
pythontech 0:5868e8752d44 578 PUSH_EXC_BLOCK(1);
pythontech 0:5868e8752d44 579 PUSH(ret);
pythontech 0:5868e8752d44 580 // stack: (..., __exit__, ctx_mgr, as_value)
pythontech 0:5868e8752d44 581 DISPATCH();
pythontech 0:5868e8752d44 582 }
pythontech 0:5868e8752d44 583
pythontech 0:5868e8752d44 584 ENTRY(MP_BC_WITH_CLEANUP): {
pythontech 0:5868e8752d44 585 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 586 // Arriving here, there's "exception control block" on top of stack,
pythontech 0:5868e8752d44 587 // and __exit__ method (with self) underneath it. Bytecode calls __exit__,
pythontech 0:5868e8752d44 588 // and "deletes" it off stack, shifting "exception control block"
pythontech 0:5868e8752d44 589 // to its place.
pythontech 0:5868e8752d44 590 if (TOP() == mp_const_none) {
pythontech 0:5868e8752d44 591 // stack: (..., __exit__, ctx_mgr, None)
pythontech 0:5868e8752d44 592 sp[1] = mp_const_none;
pythontech 0:5868e8752d44 593 sp[2] = mp_const_none;
pythontech 0:5868e8752d44 594 sp -= 2;
pythontech 0:5868e8752d44 595 mp_call_method_n_kw(3, 0, sp);
pythontech 0:5868e8752d44 596 SET_TOP(mp_const_none);
pythontech 0:5868e8752d44 597 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
pythontech 0:5868e8752d44 598 mp_int_t cause_val = MP_OBJ_SMALL_INT_VALUE(TOP());
pythontech 0:5868e8752d44 599 if (cause_val == UNWIND_RETURN) {
pythontech 0:5868e8752d44 600 // stack: (..., __exit__, ctx_mgr, ret_val, UNWIND_RETURN)
pythontech 0:5868e8752d44 601 mp_obj_t ret_val = sp[-1];
pythontech 0:5868e8752d44 602 sp[-1] = mp_const_none;
pythontech 0:5868e8752d44 603 sp[0] = mp_const_none;
pythontech 0:5868e8752d44 604 sp[1] = mp_const_none;
pythontech 0:5868e8752d44 605 mp_call_method_n_kw(3, 0, sp - 3);
pythontech 0:5868e8752d44 606 sp[-3] = ret_val;
pythontech 0:5868e8752d44 607 sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN);
pythontech 0:5868e8752d44 608 } else {
pythontech 0:5868e8752d44 609 assert(cause_val == UNWIND_JUMP);
pythontech 0:5868e8752d44 610 // stack: (..., __exit__, ctx_mgr, dest_ip, num_exc, UNWIND_JUMP)
pythontech 0:5868e8752d44 611 mp_obj_t dest_ip = sp[-2];
pythontech 0:5868e8752d44 612 mp_obj_t num_exc = sp[-1];
pythontech 0:5868e8752d44 613 sp[-2] = mp_const_none;
pythontech 0:5868e8752d44 614 sp[-1] = mp_const_none;
pythontech 0:5868e8752d44 615 sp[0] = mp_const_none;
pythontech 0:5868e8752d44 616 mp_call_method_n_kw(3, 0, sp - 4);
pythontech 0:5868e8752d44 617 sp[-4] = dest_ip;
pythontech 0:5868e8752d44 618 sp[-3] = num_exc;
pythontech 0:5868e8752d44 619 sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP);
pythontech 0:5868e8752d44 620 }
pythontech 0:5868e8752d44 621 sp -= 2; // we removed (__exit__, ctx_mgr)
pythontech 0:5868e8752d44 622 } else {
pythontech 0:5868e8752d44 623 assert(mp_obj_is_exception_type(TOP()));
pythontech 0:5868e8752d44 624 // stack: (..., __exit__, ctx_mgr, traceback, exc_val, exc_type)
pythontech 0:5868e8752d44 625 // Need to pass (sp[0], sp[-1], sp[-2]) as arguments so must reverse the
pythontech 0:5868e8752d44 626 // order of these on the value stack (don't want to create a temporary
pythontech 0:5868e8752d44 627 // array because it increases stack footprint of the VM).
pythontech 0:5868e8752d44 628 mp_obj_t obj = sp[-2];
pythontech 0:5868e8752d44 629 sp[-2] = sp[0];
pythontech 0:5868e8752d44 630 sp[0] = obj;
pythontech 0:5868e8752d44 631 mp_obj_t ret_value = mp_call_method_n_kw(3, 0, sp - 4);
pythontech 0:5868e8752d44 632 if (mp_obj_is_true(ret_value)) {
pythontech 0:5868e8752d44 633 // We need to silence/swallow the exception. This is done
pythontech 0:5868e8752d44 634 // by popping the exception and the __exit__ handler and
pythontech 0:5868e8752d44 635 // replacing it with None, which signals END_FINALLY to just
pythontech 0:5868e8752d44 636 // execute the finally handler normally.
pythontech 0:5868e8752d44 637 sp -= 4;
pythontech 0:5868e8752d44 638 SET_TOP(mp_const_none);
pythontech 0:5868e8752d44 639 assert(exc_sp >= exc_stack);
pythontech 0:5868e8752d44 640 POP_EXC_BLOCK();
pythontech 0:5868e8752d44 641 } else {
pythontech 0:5868e8752d44 642 // We need to re-raise the exception. We pop __exit__ handler
pythontech 0:5868e8752d44 643 // and copy the 3 exception values down (remembering that they
pythontech 0:5868e8752d44 644 // are reversed due to above code).
pythontech 0:5868e8752d44 645 sp[-4] = sp[0];
pythontech 0:5868e8752d44 646 sp[-3] = sp[-1];
pythontech 0:5868e8752d44 647 sp -= 2;
pythontech 0:5868e8752d44 648 }
pythontech 0:5868e8752d44 649 }
pythontech 0:5868e8752d44 650 DISPATCH();
pythontech 0:5868e8752d44 651 }
pythontech 0:5868e8752d44 652
pythontech 0:5868e8752d44 653 ENTRY(MP_BC_UNWIND_JUMP): {
pythontech 0:5868e8752d44 654 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 655 DECODE_SLABEL;
pythontech 0:5868e8752d44 656 PUSH((mp_obj_t)(mp_uint_t)(uintptr_t)(ip + slab)); // push destination ip for jump
pythontech 0:5868e8752d44 657 PUSH((mp_obj_t)(mp_uint_t)(*ip)); // push number of exception handlers to unwind (0x80 bit set if we also need to pop stack)
pythontech 0:5868e8752d44 658 unwind_jump:;
pythontech 0:5868e8752d44 659 mp_uint_t unum = (mp_uint_t)POP(); // get number of exception handlers to unwind
pythontech 0:5868e8752d44 660 while ((unum & 0x7f) > 0) {
pythontech 0:5868e8752d44 661 unum -= 1;
pythontech 0:5868e8752d44 662 assert(exc_sp >= exc_stack);
pythontech 0:5868e8752d44 663 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
pythontech 0:5868e8752d44 664 // Getting here the stack looks like:
pythontech 0:5868e8752d44 665 // (..., X, dest_ip)
pythontech 0:5868e8752d44 666 // where X is pointed to by exc_sp->val_sp and in the case
pythontech 0:5868e8752d44 667 // of a "with" block contains the context manager info.
pythontech 0:5868e8752d44 668 // We're going to run "finally" code as a coroutine
pythontech 0:5868e8752d44 669 // (not calling it recursively). Set up a sentinel
pythontech 0:5868e8752d44 670 // on a stack so it can return back to us when it is
pythontech 0:5868e8752d44 671 // done (when WITH_CLEANUP or END_FINALLY reached).
pythontech 0:5868e8752d44 672 PUSH((mp_obj_t)unum); // push number of exception handlers left to unwind
pythontech 0:5868e8752d44 673 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
pythontech 0:5868e8752d44 674 ip = exc_sp->handler; // get exception handler byte code address
pythontech 0:5868e8752d44 675 exc_sp--; // pop exception handler
pythontech 0:5868e8752d44 676 goto dispatch_loop; // run the exception handler
pythontech 0:5868e8752d44 677 }
pythontech 0:5868e8752d44 678 POP_EXC_BLOCK();
pythontech 0:5868e8752d44 679 }
pythontech 0:5868e8752d44 680 ip = (const byte*)MP_OBJ_TO_PTR(POP()); // pop destination ip for jump
pythontech 0:5868e8752d44 681 if (unum != 0) {
pythontech 0:5868e8752d44 682 sp--;
pythontech 0:5868e8752d44 683 }
pythontech 0:5868e8752d44 684 DISPATCH_WITH_PEND_EXC_CHECK();
pythontech 0:5868e8752d44 685 }
pythontech 0:5868e8752d44 686
pythontech 0:5868e8752d44 687 // matched against: POP_BLOCK or POP_EXCEPT (anything else?)
pythontech 0:5868e8752d44 688 ENTRY(MP_BC_SETUP_EXCEPT):
pythontech 0:5868e8752d44 689 ENTRY(MP_BC_SETUP_FINALLY): {
pythontech 0:5868e8752d44 690 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 691 #if SELECTIVE_EXC_IP
pythontech 0:5868e8752d44 692 PUSH_EXC_BLOCK((code_state->ip[-1] == MP_BC_SETUP_FINALLY) ? 1 : 0);
pythontech 0:5868e8752d44 693 #else
pythontech 0:5868e8752d44 694 PUSH_EXC_BLOCK((code_state->ip[0] == MP_BC_SETUP_FINALLY) ? 1 : 0);
pythontech 0:5868e8752d44 695 #endif
pythontech 0:5868e8752d44 696 DISPATCH();
pythontech 0:5868e8752d44 697 }
pythontech 0:5868e8752d44 698
pythontech 0:5868e8752d44 699 ENTRY(MP_BC_END_FINALLY):
pythontech 0:5868e8752d44 700 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 701 // not fully implemented
pythontech 0:5868e8752d44 702 // if TOS is an exception, reraises the exception (3 values on TOS)
pythontech 0:5868e8752d44 703 // if TOS is None, just pops it and continues
pythontech 0:5868e8752d44 704 // if TOS is an integer, does something else
pythontech 0:5868e8752d44 705 // else error
pythontech 0:5868e8752d44 706 if (mp_obj_is_exception_type(TOP())) {
pythontech 0:5868e8752d44 707 RAISE(sp[-1]);
pythontech 0:5868e8752d44 708 }
pythontech 0:5868e8752d44 709 if (TOP() == mp_const_none) {
pythontech 0:5868e8752d44 710 sp--;
pythontech 0:5868e8752d44 711 } else {
pythontech 0:5868e8752d44 712 assert(MP_OBJ_IS_SMALL_INT(TOP()));
pythontech 0:5868e8752d44 713 // We finished "finally" coroutine and now dispatch back
pythontech 0:5868e8752d44 714 // to our caller, based on TOS value
pythontech 0:5868e8752d44 715 mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());
pythontech 0:5868e8752d44 716 if (reason == UNWIND_RETURN) {
pythontech 0:5868e8752d44 717 goto unwind_return;
pythontech 0:5868e8752d44 718 } else {
pythontech 0:5868e8752d44 719 assert(reason == UNWIND_JUMP);
pythontech 0:5868e8752d44 720 goto unwind_jump;
pythontech 0:5868e8752d44 721 }
pythontech 0:5868e8752d44 722 }
pythontech 0:5868e8752d44 723 DISPATCH();
pythontech 0:5868e8752d44 724
pythontech 0:5868e8752d44 725 ENTRY(MP_BC_GET_ITER):
pythontech 0:5868e8752d44 726 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 727 SET_TOP(mp_getiter(TOP()));
pythontech 0:5868e8752d44 728 DISPATCH();
pythontech 0:5868e8752d44 729
pythontech 0:5868e8752d44 730 ENTRY(MP_BC_FOR_ITER): {
pythontech 0:5868e8752d44 731 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 732 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
pythontech 0:5868e8752d44 733 code_state->sp = sp;
pythontech 0:5868e8752d44 734 assert(TOP());
pythontech 0:5868e8752d44 735 mp_obj_t value = mp_iternext_allow_raise(TOP());
pythontech 0:5868e8752d44 736 if (value == MP_OBJ_STOP_ITERATION) {
pythontech 0:5868e8752d44 737 --sp; // pop the exhausted iterator
pythontech 0:5868e8752d44 738 ip += ulab; // jump to after for-block
pythontech 0:5868e8752d44 739 } else {
pythontech 0:5868e8752d44 740 PUSH(value); // push the next iteration value
pythontech 0:5868e8752d44 741 }
pythontech 0:5868e8752d44 742 DISPATCH();
pythontech 0:5868e8752d44 743 }
pythontech 0:5868e8752d44 744
pythontech 0:5868e8752d44 745 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
pythontech 0:5868e8752d44 746 ENTRY(MP_BC_POP_BLOCK):
pythontech 0:5868e8752d44 747 // we are exiting an exception handler, so pop the last one of the exception-stack
pythontech 0:5868e8752d44 748 assert(exc_sp >= exc_stack);
pythontech 0:5868e8752d44 749 POP_EXC_BLOCK();
pythontech 0:5868e8752d44 750 DISPATCH();
pythontech 0:5868e8752d44 751
pythontech 0:5868e8752d44 752 // matched against: SETUP_EXCEPT
pythontech 0:5868e8752d44 753 ENTRY(MP_BC_POP_EXCEPT):
pythontech 0:5868e8752d44 754 // TODO need to work out how blocks work etc
pythontech 0:5868e8752d44 755 // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
pythontech 0:5868e8752d44 756 assert(exc_sp >= exc_stack);
pythontech 0:5868e8752d44 757 assert(currently_in_except_block);
pythontech 0:5868e8752d44 758 //sp = (mp_obj_t*)(*exc_sp--);
pythontech 0:5868e8752d44 759 //exc_sp--; // discard ip
pythontech 0:5868e8752d44 760 POP_EXC_BLOCK();
pythontech 0:5868e8752d44 761 //sp -= 3; // pop 3 exception values
pythontech 0:5868e8752d44 762 DISPATCH();
pythontech 0:5868e8752d44 763
pythontech 0:5868e8752d44 764 ENTRY(MP_BC_BUILD_TUPLE): {
pythontech 0:5868e8752d44 765 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 766 DECODE_UINT;
pythontech 0:5868e8752d44 767 sp -= unum - 1;
pythontech 0:5868e8752d44 768 SET_TOP(mp_obj_new_tuple(unum, sp));
pythontech 0:5868e8752d44 769 DISPATCH();
pythontech 0:5868e8752d44 770 }
pythontech 0:5868e8752d44 771
pythontech 0:5868e8752d44 772 ENTRY(MP_BC_BUILD_LIST): {
pythontech 0:5868e8752d44 773 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 774 DECODE_UINT;
pythontech 0:5868e8752d44 775 sp -= unum - 1;
pythontech 0:5868e8752d44 776 SET_TOP(mp_obj_new_list(unum, sp));
pythontech 0:5868e8752d44 777 DISPATCH();
pythontech 0:5868e8752d44 778 }
pythontech 0:5868e8752d44 779
pythontech 0:5868e8752d44 780 ENTRY(MP_BC_LIST_APPEND): {
pythontech 0:5868e8752d44 781 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 782 DECODE_UINT;
pythontech 0:5868e8752d44 783 // I think it's guaranteed by the compiler that sp[unum] is a list
pythontech 0:5868e8752d44 784 mp_obj_list_append(sp[-unum], sp[0]);
pythontech 0:5868e8752d44 785 sp--;
pythontech 0:5868e8752d44 786 DISPATCH();
pythontech 0:5868e8752d44 787 }
pythontech 0:5868e8752d44 788
pythontech 0:5868e8752d44 789 ENTRY(MP_BC_BUILD_MAP): {
pythontech 0:5868e8752d44 790 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 791 DECODE_UINT;
pythontech 0:5868e8752d44 792 PUSH(mp_obj_new_dict(unum));
pythontech 0:5868e8752d44 793 DISPATCH();
pythontech 0:5868e8752d44 794 }
pythontech 0:5868e8752d44 795
pythontech 0:5868e8752d44 796 ENTRY(MP_BC_STORE_MAP):
pythontech 0:5868e8752d44 797 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 798 sp -= 2;
pythontech 0:5868e8752d44 799 mp_obj_dict_store(sp[0], sp[2], sp[1]);
pythontech 0:5868e8752d44 800 DISPATCH();
pythontech 0:5868e8752d44 801
pythontech 0:5868e8752d44 802 ENTRY(MP_BC_MAP_ADD): {
pythontech 0:5868e8752d44 803 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 804 DECODE_UINT;
pythontech 0:5868e8752d44 805 // I think it's guaranteed by the compiler that sp[-unum - 1] is a map
pythontech 0:5868e8752d44 806 mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]);
pythontech 0:5868e8752d44 807 sp -= 2;
pythontech 0:5868e8752d44 808 DISPATCH();
pythontech 0:5868e8752d44 809 }
pythontech 0:5868e8752d44 810
pythontech 0:5868e8752d44 811 #if MICROPY_PY_BUILTINS_SET
pythontech 0:5868e8752d44 812 ENTRY(MP_BC_BUILD_SET): {
pythontech 0:5868e8752d44 813 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 814 DECODE_UINT;
pythontech 0:5868e8752d44 815 sp -= unum - 1;
pythontech 0:5868e8752d44 816 SET_TOP(mp_obj_new_set(unum, sp));
pythontech 0:5868e8752d44 817 DISPATCH();
pythontech 0:5868e8752d44 818 }
pythontech 0:5868e8752d44 819
pythontech 0:5868e8752d44 820 ENTRY(MP_BC_SET_ADD): {
pythontech 0:5868e8752d44 821 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 822 DECODE_UINT;
pythontech 0:5868e8752d44 823 // I think it's guaranteed by the compiler that sp[-unum] is a set
pythontech 0:5868e8752d44 824 mp_obj_set_store(sp[-unum], sp[0]);
pythontech 0:5868e8752d44 825 sp--;
pythontech 0:5868e8752d44 826 DISPATCH();
pythontech 0:5868e8752d44 827 }
pythontech 0:5868e8752d44 828 #endif
pythontech 0:5868e8752d44 829
pythontech 0:5868e8752d44 830 #if MICROPY_PY_BUILTINS_SLICE
pythontech 0:5868e8752d44 831 ENTRY(MP_BC_BUILD_SLICE): {
pythontech 0:5868e8752d44 832 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 833 DECODE_UINT;
pythontech 0:5868e8752d44 834 if (unum == 2) {
pythontech 0:5868e8752d44 835 mp_obj_t stop = POP();
pythontech 0:5868e8752d44 836 mp_obj_t start = TOP();
pythontech 0:5868e8752d44 837 SET_TOP(mp_obj_new_slice(start, stop, mp_const_none));
pythontech 0:5868e8752d44 838 } else {
pythontech 0:5868e8752d44 839 mp_obj_t step = POP();
pythontech 0:5868e8752d44 840 mp_obj_t stop = POP();
pythontech 0:5868e8752d44 841 mp_obj_t start = TOP();
pythontech 0:5868e8752d44 842 SET_TOP(mp_obj_new_slice(start, stop, step));
pythontech 0:5868e8752d44 843 }
pythontech 0:5868e8752d44 844 DISPATCH();
pythontech 0:5868e8752d44 845 }
pythontech 0:5868e8752d44 846 #endif
pythontech 0:5868e8752d44 847
pythontech 0:5868e8752d44 848 ENTRY(MP_BC_UNPACK_SEQUENCE): {
pythontech 0:5868e8752d44 849 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 850 DECODE_UINT;
pythontech 0:5868e8752d44 851 mp_unpack_sequence(sp[0], unum, sp);
pythontech 0:5868e8752d44 852 sp += unum - 1;
pythontech 0:5868e8752d44 853 DISPATCH();
pythontech 0:5868e8752d44 854 }
pythontech 0:5868e8752d44 855
pythontech 0:5868e8752d44 856 ENTRY(MP_BC_UNPACK_EX): {
pythontech 0:5868e8752d44 857 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 858 DECODE_UINT;
pythontech 0:5868e8752d44 859 mp_unpack_ex(sp[0], unum, sp);
pythontech 0:5868e8752d44 860 sp += (unum & 0xff) + ((unum >> 8) & 0xff);
pythontech 0:5868e8752d44 861 DISPATCH();
pythontech 0:5868e8752d44 862 }
pythontech 0:5868e8752d44 863
pythontech 0:5868e8752d44 864 ENTRY(MP_BC_MAKE_FUNCTION): {
pythontech 0:5868e8752d44 865 DECODE_PTR;
pythontech 0:5868e8752d44 866 PUSH(mp_make_function_from_raw_code(ptr, MP_OBJ_NULL, MP_OBJ_NULL));
pythontech 0:5868e8752d44 867 DISPATCH();
pythontech 0:5868e8752d44 868 }
pythontech 0:5868e8752d44 869
pythontech 0:5868e8752d44 870 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
pythontech 0:5868e8752d44 871 DECODE_PTR;
pythontech 0:5868e8752d44 872 // Stack layout: def_tuple def_dict <- TOS
pythontech 0:5868e8752d44 873 mp_obj_t def_dict = POP();
pythontech 0:5868e8752d44 874 SET_TOP(mp_make_function_from_raw_code(ptr, TOP(), def_dict));
pythontech 0:5868e8752d44 875 DISPATCH();
pythontech 0:5868e8752d44 876 }
pythontech 0:5868e8752d44 877
pythontech 0:5868e8752d44 878 ENTRY(MP_BC_MAKE_CLOSURE): {
pythontech 0:5868e8752d44 879 DECODE_PTR;
pythontech 0:5868e8752d44 880 mp_uint_t n_closed_over = *ip++;
pythontech 0:5868e8752d44 881 // Stack layout: closed_overs <- TOS
pythontech 0:5868e8752d44 882 sp -= n_closed_over - 1;
pythontech 0:5868e8752d44 883 SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp));
pythontech 0:5868e8752d44 884 DISPATCH();
pythontech 0:5868e8752d44 885 }
pythontech 0:5868e8752d44 886
pythontech 0:5868e8752d44 887 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
pythontech 0:5868e8752d44 888 DECODE_PTR;
pythontech 0:5868e8752d44 889 mp_uint_t n_closed_over = *ip++;
pythontech 0:5868e8752d44 890 // Stack layout: def_tuple def_dict closed_overs <- TOS
pythontech 0:5868e8752d44 891 sp -= 2 + n_closed_over - 1;
pythontech 0:5868e8752d44 892 SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp));
pythontech 0:5868e8752d44 893 DISPATCH();
pythontech 0:5868e8752d44 894 }
pythontech 0:5868e8752d44 895
pythontech 0:5868e8752d44 896 ENTRY(MP_BC_CALL_FUNCTION): {
pythontech 0:5868e8752d44 897 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 898 DECODE_UINT;
pythontech 0:5868e8752d44 899 // unum & 0xff == n_positional
pythontech 0:5868e8752d44 900 // (unum >> 8) & 0xff == n_keyword
pythontech 0:5868e8752d44 901 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
pythontech 0:5868e8752d44 902 #if MICROPY_STACKLESS
pythontech 0:5868e8752d44 903 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
pythontech 0:5868e8752d44 904 code_state->ip = ip;
pythontech 0:5868e8752d44 905 code_state->sp = sp;
pythontech 0:5868e8752d44 906 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
pythontech 0:5868e8752d44 907 mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1);
pythontech 0:5868e8752d44 908 if (new_state) {
pythontech 0:5868e8752d44 909 new_state->prev = code_state;
pythontech 0:5868e8752d44 910 code_state = new_state;
pythontech 0:5868e8752d44 911 nlr_pop();
pythontech 0:5868e8752d44 912 goto run_code_state;
pythontech 0:5868e8752d44 913 }
pythontech 0:5868e8752d44 914 #if MICROPY_STACKLESS_STRICT
pythontech 0:5868e8752d44 915 else {
pythontech 0:5868e8752d44 916 deep_recursion_error:
pythontech 0:5868e8752d44 917 mp_exc_recursion_depth();
pythontech 0:5868e8752d44 918 }
pythontech 0:5868e8752d44 919 #endif
pythontech 0:5868e8752d44 920 }
pythontech 0:5868e8752d44 921 #endif
pythontech 0:5868e8752d44 922 SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
pythontech 0:5868e8752d44 923 DISPATCH();
pythontech 0:5868e8752d44 924 }
pythontech 0:5868e8752d44 925
pythontech 0:5868e8752d44 926 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): {
pythontech 0:5868e8752d44 927 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 928 DECODE_UINT;
pythontech 0:5868e8752d44 929 // unum & 0xff == n_positional
pythontech 0:5868e8752d44 930 // (unum >> 8) & 0xff == n_keyword
pythontech 0:5868e8752d44 931 // We have folowing stack layout here:
pythontech 0:5868e8752d44 932 // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
pythontech 0:5868e8752d44 933 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
pythontech 0:5868e8752d44 934 #if MICROPY_STACKLESS
pythontech 0:5868e8752d44 935 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
pythontech 0:5868e8752d44 936 code_state->ip = ip;
pythontech 0:5868e8752d44 937 code_state->sp = sp;
pythontech 0:5868e8752d44 938 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
pythontech 0:5868e8752d44 939
pythontech 0:5868e8752d44 940 mp_call_args_t out_args;
pythontech 0:5868e8752d44 941 mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args);
pythontech 0:5868e8752d44 942
pythontech 0:5868e8752d44 943 mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
pythontech 0:5868e8752d44 944 out_args.n_args, out_args.n_kw, out_args.args);
pythontech 0:5868e8752d44 945 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
pythontech 0:5868e8752d44 946 if (new_state) {
pythontech 0:5868e8752d44 947 new_state->prev = code_state;
pythontech 0:5868e8752d44 948 code_state = new_state;
pythontech 0:5868e8752d44 949 nlr_pop();
pythontech 0:5868e8752d44 950 goto run_code_state;
pythontech 0:5868e8752d44 951 }
pythontech 0:5868e8752d44 952 #if MICROPY_STACKLESS_STRICT
pythontech 0:5868e8752d44 953 else {
pythontech 0:5868e8752d44 954 goto deep_recursion_error;
pythontech 0:5868e8752d44 955 }
pythontech 0:5868e8752d44 956 #endif
pythontech 0:5868e8752d44 957 }
pythontech 0:5868e8752d44 958 #endif
pythontech 0:5868e8752d44 959 SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
pythontech 0:5868e8752d44 960 DISPATCH();
pythontech 0:5868e8752d44 961 }
pythontech 0:5868e8752d44 962
pythontech 0:5868e8752d44 963 ENTRY(MP_BC_CALL_METHOD): {
pythontech 0:5868e8752d44 964 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 965 DECODE_UINT;
pythontech 0:5868e8752d44 966 // unum & 0xff == n_positional
pythontech 0:5868e8752d44 967 // (unum >> 8) & 0xff == n_keyword
pythontech 0:5868e8752d44 968 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
pythontech 0:5868e8752d44 969 #if MICROPY_STACKLESS
pythontech 0:5868e8752d44 970 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
pythontech 0:5868e8752d44 971 code_state->ip = ip;
pythontech 0:5868e8752d44 972 code_state->sp = sp;
pythontech 0:5868e8752d44 973 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
pythontech 0:5868e8752d44 974
pythontech 0:5868e8752d44 975 mp_uint_t n_args = unum & 0xff;
pythontech 0:5868e8752d44 976 mp_uint_t n_kw = (unum >> 8) & 0xff;
pythontech 0:5868e8752d44 977 int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1;
pythontech 0:5868e8752d44 978
pythontech 0:5868e8752d44 979 mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust);
pythontech 0:5868e8752d44 980 if (new_state) {
pythontech 0:5868e8752d44 981 new_state->prev = code_state;
pythontech 0:5868e8752d44 982 code_state = new_state;
pythontech 0:5868e8752d44 983 nlr_pop();
pythontech 0:5868e8752d44 984 goto run_code_state;
pythontech 0:5868e8752d44 985 }
pythontech 0:5868e8752d44 986 #if MICROPY_STACKLESS_STRICT
pythontech 0:5868e8752d44 987 else {
pythontech 0:5868e8752d44 988 goto deep_recursion_error;
pythontech 0:5868e8752d44 989 }
pythontech 0:5868e8752d44 990 #endif
pythontech 0:5868e8752d44 991 }
pythontech 0:5868e8752d44 992 #endif
pythontech 0:5868e8752d44 993 SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
pythontech 0:5868e8752d44 994 DISPATCH();
pythontech 0:5868e8752d44 995 }
pythontech 0:5868e8752d44 996
pythontech 0:5868e8752d44 997 ENTRY(MP_BC_CALL_METHOD_VAR_KW): {
pythontech 0:5868e8752d44 998 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 999 DECODE_UINT;
pythontech 0:5868e8752d44 1000 // unum & 0xff == n_positional
pythontech 0:5868e8752d44 1001 // (unum >> 8) & 0xff == n_keyword
pythontech 0:5868e8752d44 1002 // We have folowing stack layout here:
pythontech 0:5868e8752d44 1003 // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
pythontech 0:5868e8752d44 1004 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
pythontech 0:5868e8752d44 1005 #if MICROPY_STACKLESS
pythontech 0:5868e8752d44 1006 if (mp_obj_get_type(*sp) == &mp_type_fun_bc) {
pythontech 0:5868e8752d44 1007 code_state->ip = ip;
pythontech 0:5868e8752d44 1008 code_state->sp = sp;
pythontech 0:5868e8752d44 1009 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
pythontech 0:5868e8752d44 1010
pythontech 0:5868e8752d44 1011 mp_call_args_t out_args;
pythontech 0:5868e8752d44 1012 mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args);
pythontech 0:5868e8752d44 1013
pythontech 0:5868e8752d44 1014 mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
pythontech 0:5868e8752d44 1015 out_args.n_args, out_args.n_kw, out_args.args);
pythontech 0:5868e8752d44 1016 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
pythontech 0:5868e8752d44 1017 if (new_state) {
pythontech 0:5868e8752d44 1018 new_state->prev = code_state;
pythontech 0:5868e8752d44 1019 code_state = new_state;
pythontech 0:5868e8752d44 1020 nlr_pop();
pythontech 0:5868e8752d44 1021 goto run_code_state;
pythontech 0:5868e8752d44 1022 }
pythontech 0:5868e8752d44 1023 #if MICROPY_STACKLESS_STRICT
pythontech 0:5868e8752d44 1024 else {
pythontech 0:5868e8752d44 1025 goto deep_recursion_error;
pythontech 0:5868e8752d44 1026 }
pythontech 0:5868e8752d44 1027 #endif
pythontech 0:5868e8752d44 1028 }
pythontech 0:5868e8752d44 1029 #endif
pythontech 0:5868e8752d44 1030 SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
pythontech 0:5868e8752d44 1031 DISPATCH();
pythontech 0:5868e8752d44 1032 }
pythontech 0:5868e8752d44 1033
pythontech 0:5868e8752d44 1034 ENTRY(MP_BC_RETURN_VALUE):
pythontech 0:5868e8752d44 1035 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 1036 // These next 3 lines pop a try-finally exception handler, if one
pythontech 0:5868e8752d44 1037 // is there on the exception stack. Without this the finally block
pythontech 0:5868e8752d44 1038 // is executed a second time when the return is executed, because
pythontech 0:5868e8752d44 1039 // the try-finally exception handler is still on the stack.
pythontech 0:5868e8752d44 1040 // TODO Possibly find a better way to handle this case.
pythontech 0:5868e8752d44 1041 if (currently_in_except_block) {
pythontech 0:5868e8752d44 1042 POP_EXC_BLOCK();
pythontech 0:5868e8752d44 1043 }
pythontech 0:5868e8752d44 1044 unwind_return:
pythontech 0:5868e8752d44 1045 while (exc_sp >= exc_stack) {
pythontech 0:5868e8752d44 1046 if (MP_TAGPTR_TAG1(exc_sp->val_sp)) {
pythontech 0:5868e8752d44 1047 // Getting here the stack looks like:
pythontech 0:5868e8752d44 1048 // (..., X, [iter0, iter1, ...,] ret_val)
pythontech 0:5868e8752d44 1049 // where X is pointed to by exc_sp->val_sp and in the case
pythontech 0:5868e8752d44 1050 // of a "with" block contains the context manager info.
pythontech 0:5868e8752d44 1051 // There may be 0 or more for-iterators between X and the
pythontech 0:5868e8752d44 1052 // return value, and these must be removed before control can
pythontech 0:5868e8752d44 1053 // pass to the finally code. We simply copy the ret_value down
pythontech 0:5868e8752d44 1054 // over these iterators, if they exist. If they don't then the
pythontech 0:5868e8752d44 1055 // following is a null operation.
pythontech 0:5868e8752d44 1056 mp_obj_t *finally_sp = MP_TAGPTR_PTR(exc_sp->val_sp);
pythontech 0:5868e8752d44 1057 finally_sp[1] = sp[0];
pythontech 0:5868e8752d44 1058 sp = &finally_sp[1];
pythontech 0:5868e8752d44 1059 // We're going to run "finally" code as a coroutine
pythontech 0:5868e8752d44 1060 // (not calling it recursively). Set up a sentinel
pythontech 0:5868e8752d44 1061 // on a stack so it can return back to us when it is
pythontech 0:5868e8752d44 1062 // done (when WITH_CLEANUP or END_FINALLY reached).
pythontech 0:5868e8752d44 1063 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
pythontech 0:5868e8752d44 1064 ip = exc_sp->handler;
pythontech 0:5868e8752d44 1065 exc_sp--;
pythontech 0:5868e8752d44 1066 goto dispatch_loop;
pythontech 0:5868e8752d44 1067 }
pythontech 0:5868e8752d44 1068 exc_sp--;
pythontech 0:5868e8752d44 1069 }
pythontech 0:5868e8752d44 1070 nlr_pop();
pythontech 0:5868e8752d44 1071 code_state->sp = sp;
pythontech 0:5868e8752d44 1072 assert(exc_sp == exc_stack - 1);
pythontech 0:5868e8752d44 1073 MICROPY_VM_HOOK_RETURN
pythontech 0:5868e8752d44 1074 #if MICROPY_STACKLESS
pythontech 0:5868e8752d44 1075 if (code_state->prev != NULL) {
pythontech 0:5868e8752d44 1076 mp_obj_t res = *sp;
pythontech 0:5868e8752d44 1077 mp_globals_set(code_state->old_globals);
pythontech 0:5868e8752d44 1078 code_state = code_state->prev;
pythontech 0:5868e8752d44 1079 *code_state->sp = res;
pythontech 0:5868e8752d44 1080 goto run_code_state;
pythontech 0:5868e8752d44 1081 }
pythontech 0:5868e8752d44 1082 #endif
pythontech 0:5868e8752d44 1083 return MP_VM_RETURN_NORMAL;
pythontech 0:5868e8752d44 1084
pythontech 0:5868e8752d44 1085 ENTRY(MP_BC_RAISE_VARARGS): {
pythontech 0:5868e8752d44 1086 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 1087 mp_uint_t unum = *ip++;
pythontech 0:5868e8752d44 1088 mp_obj_t obj;
pythontech 0:5868e8752d44 1089 if (unum == 2) {
pythontech 0:5868e8752d44 1090 mp_warning("exception chaining not supported");
pythontech 0:5868e8752d44 1091 // ignore (pop) "from" argument
pythontech 0:5868e8752d44 1092 sp--;
pythontech 0:5868e8752d44 1093 }
pythontech 0:5868e8752d44 1094 if (unum == 0) {
pythontech 0:5868e8752d44 1095 // search for the inner-most previous exception, to reraise it
pythontech 0:5868e8752d44 1096 obj = MP_OBJ_NULL;
pythontech 0:5868e8752d44 1097 for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
pythontech 0:5868e8752d44 1098 if (e->prev_exc != NULL) {
pythontech 0:5868e8752d44 1099 obj = MP_OBJ_FROM_PTR(e->prev_exc);
pythontech 0:5868e8752d44 1100 break;
pythontech 0:5868e8752d44 1101 }
pythontech 0:5868e8752d44 1102 }
pythontech 0:5868e8752d44 1103 if (obj == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1104 obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
pythontech 0:5868e8752d44 1105 RAISE(obj);
pythontech 0:5868e8752d44 1106 }
pythontech 0:5868e8752d44 1107 } else {
pythontech 0:5868e8752d44 1108 obj = POP();
pythontech 0:5868e8752d44 1109 }
pythontech 0:5868e8752d44 1110 obj = mp_make_raise_obj(obj);
pythontech 0:5868e8752d44 1111 RAISE(obj);
pythontech 0:5868e8752d44 1112 }
pythontech 0:5868e8752d44 1113
pythontech 0:5868e8752d44 1114 ENTRY(MP_BC_YIELD_VALUE):
pythontech 0:5868e8752d44 1115 yield:
pythontech 0:5868e8752d44 1116 nlr_pop();
pythontech 0:5868e8752d44 1117 code_state->ip = ip;
pythontech 0:5868e8752d44 1118 code_state->sp = sp;
pythontech 0:5868e8752d44 1119 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
pythontech 0:5868e8752d44 1120 return MP_VM_RETURN_YIELD;
pythontech 0:5868e8752d44 1121
pythontech 0:5868e8752d44 1122 ENTRY(MP_BC_YIELD_FROM): {
pythontech 0:5868e8752d44 1123 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 1124 //#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
pythontech 0:5868e8752d44 1125 #define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
pythontech 0:5868e8752d44 1126 #define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { RAISE(t); }
pythontech 0:5868e8752d44 1127 mp_vm_return_kind_t ret_kind;
pythontech 0:5868e8752d44 1128 mp_obj_t send_value = POP();
pythontech 0:5868e8752d44 1129 mp_obj_t t_exc = MP_OBJ_NULL;
pythontech 0:5868e8752d44 1130 mp_obj_t ret_value;
pythontech 0:5868e8752d44 1131 if (inject_exc != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1132 t_exc = inject_exc;
pythontech 0:5868e8752d44 1133 inject_exc = MP_OBJ_NULL;
pythontech 0:5868e8752d44 1134 ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
pythontech 0:5868e8752d44 1135 } else {
pythontech 0:5868e8752d44 1136 ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
pythontech 0:5868e8752d44 1137 }
pythontech 0:5868e8752d44 1138
pythontech 0:5868e8752d44 1139 if (ret_kind == MP_VM_RETURN_YIELD) {
pythontech 0:5868e8752d44 1140 ip--;
pythontech 0:5868e8752d44 1141 PUSH(ret_value);
pythontech 0:5868e8752d44 1142 goto yield;
pythontech 0:5868e8752d44 1143 }
pythontech 0:5868e8752d44 1144 if (ret_kind == MP_VM_RETURN_NORMAL) {
pythontech 0:5868e8752d44 1145 // Pop exhausted gen
pythontech 0:5868e8752d44 1146 sp--;
pythontech 0:5868e8752d44 1147 if (ret_value == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1148 // Optimize StopIteration
pythontech 0:5868e8752d44 1149 // TODO: get StopIteration's value
pythontech 0:5868e8752d44 1150 PUSH(mp_const_none);
pythontech 0:5868e8752d44 1151 } else {
pythontech 0:5868e8752d44 1152 PUSH(ret_value);
pythontech 0:5868e8752d44 1153 }
pythontech 0:5868e8752d44 1154
pythontech 0:5868e8752d44 1155 // If we injected GeneratorExit downstream, then even
pythontech 0:5868e8752d44 1156 // if it was swallowed, we re-raise GeneratorExit
pythontech 0:5868e8752d44 1157 GENERATOR_EXIT_IF_NEEDED(t_exc);
pythontech 0:5868e8752d44 1158 DISPATCH();
pythontech 0:5868e8752d44 1159 }
pythontech 0:5868e8752d44 1160 if (ret_kind == MP_VM_RETURN_EXCEPTION) {
pythontech 0:5868e8752d44 1161 // Pop exhausted gen
pythontech 0:5868e8752d44 1162 sp--;
pythontech 0:5868e8752d44 1163 if (EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
pythontech 0:5868e8752d44 1164 PUSH(mp_obj_exception_get_value(ret_value));
pythontech 0:5868e8752d44 1165 // If we injected GeneratorExit downstream, then even
pythontech 0:5868e8752d44 1166 // if it was swallowed, we re-raise GeneratorExit
pythontech 0:5868e8752d44 1167 GENERATOR_EXIT_IF_NEEDED(t_exc);
pythontech 0:5868e8752d44 1168 DISPATCH();
pythontech 0:5868e8752d44 1169 } else {
pythontech 0:5868e8752d44 1170 RAISE(ret_value);
pythontech 0:5868e8752d44 1171 }
pythontech 0:5868e8752d44 1172 }
pythontech 0:5868e8752d44 1173 }
pythontech 0:5868e8752d44 1174
pythontech 0:5868e8752d44 1175 ENTRY(MP_BC_IMPORT_NAME): {
pythontech 0:5868e8752d44 1176 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 1177 DECODE_QSTR;
pythontech 0:5868e8752d44 1178 mp_obj_t obj = POP();
pythontech 0:5868e8752d44 1179 SET_TOP(mp_import_name(qst, obj, TOP()));
pythontech 0:5868e8752d44 1180 DISPATCH();
pythontech 0:5868e8752d44 1181 }
pythontech 0:5868e8752d44 1182
pythontech 0:5868e8752d44 1183 ENTRY(MP_BC_IMPORT_FROM): {
pythontech 0:5868e8752d44 1184 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 1185 DECODE_QSTR;
pythontech 0:5868e8752d44 1186 mp_obj_t obj = mp_import_from(TOP(), qst);
pythontech 0:5868e8752d44 1187 PUSH(obj);
pythontech 0:5868e8752d44 1188 DISPATCH();
pythontech 0:5868e8752d44 1189 }
pythontech 0:5868e8752d44 1190
pythontech 0:5868e8752d44 1191 ENTRY(MP_BC_IMPORT_STAR):
pythontech 0:5868e8752d44 1192 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 1193 mp_import_all(POP());
pythontech 0:5868e8752d44 1194 DISPATCH();
pythontech 0:5868e8752d44 1195
pythontech 0:5868e8752d44 1196 #if MICROPY_OPT_COMPUTED_GOTO
pythontech 0:5868e8752d44 1197 ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):
pythontech 0:5868e8752d44 1198 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
pythontech 0:5868e8752d44 1199 DISPATCH();
pythontech 0:5868e8752d44 1200
pythontech 0:5868e8752d44 1201 ENTRY(MP_BC_LOAD_FAST_MULTI):
pythontech 0:5868e8752d44 1202 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
pythontech 0:5868e8752d44 1203 goto load_check;
pythontech 0:5868e8752d44 1204
pythontech 0:5868e8752d44 1205 ENTRY(MP_BC_STORE_FAST_MULTI):
pythontech 0:5868e8752d44 1206 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
pythontech 0:5868e8752d44 1207 DISPATCH();
pythontech 0:5868e8752d44 1208
pythontech 0:5868e8752d44 1209 ENTRY(MP_BC_UNARY_OP_MULTI):
pythontech 0:5868e8752d44 1210 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 1211 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
pythontech 0:5868e8752d44 1212 DISPATCH();
pythontech 0:5868e8752d44 1213
pythontech 0:5868e8752d44 1214 ENTRY(MP_BC_BINARY_OP_MULTI): {
pythontech 0:5868e8752d44 1215 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 1216 mp_obj_t rhs = POP();
pythontech 0:5868e8752d44 1217 mp_obj_t lhs = TOP();
pythontech 0:5868e8752d44 1218 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
pythontech 0:5868e8752d44 1219 DISPATCH();
pythontech 0:5868e8752d44 1220 }
pythontech 0:5868e8752d44 1221
pythontech 0:5868e8752d44 1222 ENTRY_DEFAULT:
pythontech 0:5868e8752d44 1223 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 1224 #else
pythontech 0:5868e8752d44 1225 ENTRY_DEFAULT:
pythontech 0:5868e8752d44 1226 if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
pythontech 0:5868e8752d44 1227 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
pythontech 0:5868e8752d44 1228 DISPATCH();
pythontech 0:5868e8752d44 1229 } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
pythontech 0:5868e8752d44 1230 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
pythontech 0:5868e8752d44 1231 goto load_check;
pythontech 0:5868e8752d44 1232 } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
pythontech 0:5868e8752d44 1233 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
pythontech 0:5868e8752d44 1234 DISPATCH();
pythontech 0:5868e8752d44 1235 } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 7) {
pythontech 0:5868e8752d44 1236 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
pythontech 0:5868e8752d44 1237 DISPATCH();
pythontech 0:5868e8752d44 1238 } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) {
pythontech 0:5868e8752d44 1239 mp_obj_t rhs = POP();
pythontech 0:5868e8752d44 1240 mp_obj_t lhs = TOP();
pythontech 0:5868e8752d44 1241 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
pythontech 0:5868e8752d44 1242 DISPATCH();
pythontech 0:5868e8752d44 1243 } else
pythontech 0:5868e8752d44 1244 #endif
pythontech 0:5868e8752d44 1245 {
pythontech 0:5868e8752d44 1246 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
pythontech 0:5868e8752d44 1247 nlr_pop();
pythontech 0:5868e8752d44 1248 fastn[0] = obj;
pythontech 0:5868e8752d44 1249 return MP_VM_RETURN_EXCEPTION;
pythontech 0:5868e8752d44 1250 }
pythontech 0:5868e8752d44 1251
pythontech 0:5868e8752d44 1252 #if !MICROPY_OPT_COMPUTED_GOTO
pythontech 0:5868e8752d44 1253 } // switch
pythontech 0:5868e8752d44 1254 #endif
pythontech 0:5868e8752d44 1255
pythontech 0:5868e8752d44 1256 pending_exception_check:
pythontech 0:5868e8752d44 1257 MICROPY_VM_HOOK_LOOP
pythontech 0:5868e8752d44 1258 if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1259 MARK_EXC_IP_SELECTIVE();
pythontech 0:5868e8752d44 1260 mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
pythontech 0:5868e8752d44 1261 MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
pythontech 0:5868e8752d44 1262 RAISE(obj);
pythontech 0:5868e8752d44 1263 }
pythontech 0:5868e8752d44 1264
pythontech 0:5868e8752d44 1265 } // for loop
pythontech 0:5868e8752d44 1266
pythontech 0:5868e8752d44 1267 } else {
pythontech 0:5868e8752d44 1268 exception_handler:
pythontech 0:5868e8752d44 1269 // exception occurred
pythontech 0:5868e8752d44 1270
pythontech 0:5868e8752d44 1271 #if MICROPY_PY_SYS_EXC_INFO
pythontech 0:5868e8752d44 1272 MP_STATE_VM(cur_exception) = nlr.ret_val;
pythontech 0:5868e8752d44 1273 #endif
pythontech 0:5868e8752d44 1274
pythontech 0:5868e8752d44 1275 #if SELECTIVE_EXC_IP
pythontech 0:5868e8752d44 1276 // with selective ip, we store the ip 1 byte past the opcode, so move ptr back
pythontech 0:5868e8752d44 1277 code_state->ip -= 1;
pythontech 0:5868e8752d44 1278 #endif
pythontech 0:5868e8752d44 1279
pythontech 0:5868e8752d44 1280 if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
pythontech 0:5868e8752d44 1281 if (code_state->ip) {
pythontech 0:5868e8752d44 1282 // check if it's a StopIteration within a for block
pythontech 0:5868e8752d44 1283 if (*code_state->ip == MP_BC_FOR_ITER) {
pythontech 0:5868e8752d44 1284 const byte *ip = code_state->ip + 1;
pythontech 0:5868e8752d44 1285 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
pythontech 0:5868e8752d44 1286 code_state->ip = ip + ulab; // jump to after for-block
pythontech 0:5868e8752d44 1287 code_state->sp -= 1; // pop the exhausted iterator
pythontech 0:5868e8752d44 1288 goto outer_dispatch_loop; // continue with dispatch loop
pythontech 0:5868e8752d44 1289 } else if (*code_state->ip == MP_BC_YIELD_FROM) {
pythontech 0:5868e8752d44 1290 // StopIteration inside yield from call means return a value of
pythontech 0:5868e8752d44 1291 // yield from, so inject exception's value as yield from's result
pythontech 0:5868e8752d44 1292 *++code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));
pythontech 0:5868e8752d44 1293 code_state->ip++; // yield from is over, move to next instruction
pythontech 0:5868e8752d44 1294 goto outer_dispatch_loop; // continue with dispatch loop
pythontech 0:5868e8752d44 1295 }
pythontech 0:5868e8752d44 1296 }
pythontech 0:5868e8752d44 1297 }
pythontech 0:5868e8752d44 1298
pythontech 0:5868e8752d44 1299 #if MICROPY_STACKLESS
pythontech 0:5868e8752d44 1300 unwind_loop:
pythontech 0:5868e8752d44 1301 #endif
pythontech 0:5868e8752d44 1302 // set file and line number that the exception occurred at
pythontech 0:5868e8752d44 1303 // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
pythontech 0:5868e8752d44 1304 // But consider how to handle nested exceptions.
pythontech 0:5868e8752d44 1305 // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
pythontech 0:5868e8752d44 1306 if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
pythontech 0:5868e8752d44 1307 const byte *ip = code_state->code_info;
pythontech 0:5868e8752d44 1308 mp_uint_t code_info_size = mp_decode_uint(&ip);
pythontech 0:5868e8752d44 1309 #if MICROPY_PERSISTENT_CODE
pythontech 0:5868e8752d44 1310 qstr block_name = ip[0] | (ip[1] << 8);
pythontech 0:5868e8752d44 1311 qstr source_file = ip[2] | (ip[3] << 8);
pythontech 0:5868e8752d44 1312 ip += 4;
pythontech 0:5868e8752d44 1313 #else
pythontech 0:5868e8752d44 1314 qstr block_name = mp_decode_uint(&ip);
pythontech 0:5868e8752d44 1315 qstr source_file = mp_decode_uint(&ip);
pythontech 0:5868e8752d44 1316 #endif
pythontech 0:5868e8752d44 1317 size_t bc = code_state->ip - code_state->code_info - code_info_size;
pythontech 0:5868e8752d44 1318 size_t source_line = 1;
pythontech 0:5868e8752d44 1319 size_t c;
pythontech 0:5868e8752d44 1320 while ((c = *ip)) {
pythontech 0:5868e8752d44 1321 mp_uint_t b, l;
pythontech 0:5868e8752d44 1322 if ((c & 0x80) == 0) {
pythontech 0:5868e8752d44 1323 // 0b0LLBBBBB encoding
pythontech 0:5868e8752d44 1324 b = c & 0x1f;
pythontech 0:5868e8752d44 1325 l = c >> 5;
pythontech 0:5868e8752d44 1326 ip += 1;
pythontech 0:5868e8752d44 1327 } else {
pythontech 0:5868e8752d44 1328 // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
pythontech 0:5868e8752d44 1329 b = c & 0xf;
pythontech 0:5868e8752d44 1330 l = ((c << 4) & 0x700) | ip[1];
pythontech 0:5868e8752d44 1331 ip += 2;
pythontech 0:5868e8752d44 1332 }
pythontech 0:5868e8752d44 1333 if (bc >= b) {
pythontech 0:5868e8752d44 1334 bc -= b;
pythontech 0:5868e8752d44 1335 source_line += l;
pythontech 0:5868e8752d44 1336 } else {
pythontech 0:5868e8752d44 1337 // found source line corresponding to bytecode offset
pythontech 0:5868e8752d44 1338 break;
pythontech 0:5868e8752d44 1339 }
pythontech 0:5868e8752d44 1340 }
pythontech 0:5868e8752d44 1341 mp_obj_exception_add_traceback(MP_OBJ_FROM_PTR(nlr.ret_val), source_file, source_line, block_name);
pythontech 0:5868e8752d44 1342 }
pythontech 0:5868e8752d44 1343
pythontech 0:5868e8752d44 1344 while (currently_in_except_block) {
pythontech 0:5868e8752d44 1345 // nested exception
pythontech 0:5868e8752d44 1346
pythontech 0:5868e8752d44 1347 assert(exc_sp >= exc_stack);
pythontech 0:5868e8752d44 1348
pythontech 0:5868e8752d44 1349 // TODO make a proper message for nested exception
pythontech 0:5868e8752d44 1350 // at the moment we are just raising the very last exception (the one that caused the nested exception)
pythontech 0:5868e8752d44 1351
pythontech 0:5868e8752d44 1352 // move up to previous exception handler
pythontech 0:5868e8752d44 1353 POP_EXC_BLOCK();
pythontech 0:5868e8752d44 1354 }
pythontech 0:5868e8752d44 1355
pythontech 0:5868e8752d44 1356 if (exc_sp >= exc_stack) {
pythontech 0:5868e8752d44 1357 // set flag to indicate that we are now handling an exception
pythontech 0:5868e8752d44 1358 currently_in_except_block = 1;
pythontech 0:5868e8752d44 1359
pythontech 0:5868e8752d44 1360 // catch exception and pass to byte code
pythontech 0:5868e8752d44 1361 code_state->ip = exc_sp->handler;
pythontech 0:5868e8752d44 1362 mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
pythontech 0:5868e8752d44 1363 // save this exception in the stack so it can be used in a reraise, if needed
pythontech 0:5868e8752d44 1364 exc_sp->prev_exc = nlr.ret_val;
pythontech 0:5868e8752d44 1365 // push(traceback, exc-val, exc-type)
pythontech 0:5868e8752d44 1366 PUSH(mp_const_none);
pythontech 0:5868e8752d44 1367 PUSH(MP_OBJ_FROM_PTR(nlr.ret_val));
pythontech 0:5868e8752d44 1368 PUSH(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type));
pythontech 0:5868e8752d44 1369 code_state->sp = sp;
pythontech 0:5868e8752d44 1370
pythontech 0:5868e8752d44 1371 #if MICROPY_STACKLESS
pythontech 0:5868e8752d44 1372 } else if (code_state->prev != NULL) {
pythontech 0:5868e8752d44 1373 mp_globals_set(code_state->old_globals);
pythontech 0:5868e8752d44 1374 code_state = code_state->prev;
pythontech 0:5868e8752d44 1375 fastn = &code_state->state[code_state->n_state - 1];
pythontech 0:5868e8752d44 1376 exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
pythontech 0:5868e8752d44 1377 // variables that are visible to the exception handler (declared volatile)
pythontech 0:5868e8752d44 1378 currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
pythontech 0:5868e8752d44 1379 exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
pythontech 0:5868e8752d44 1380 goto unwind_loop;
pythontech 0:5868e8752d44 1381
pythontech 0:5868e8752d44 1382 #endif
pythontech 0:5868e8752d44 1383 } else {
pythontech 0:5868e8752d44 1384 // propagate exception to higher level
pythontech 0:5868e8752d44 1385 // TODO what to do about ip and sp? they don't really make sense at this point
pythontech 0:5868e8752d44 1386 fastn[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // must put exception here because sp is invalid
pythontech 0:5868e8752d44 1387 return MP_VM_RETURN_EXCEPTION;
pythontech 0:5868e8752d44 1388 }
pythontech 0:5868e8752d44 1389 }
pythontech 0:5868e8752d44 1390 }
pythontech 0:5868e8752d44 1391 }