blob: 664f9377a8671eb828c0f41e59f9769e8e772150 [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
2 * This file is part of the Micro Python project, http://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2013, 2014 Damien P. George
Paul Sokolovskyda9f0922014-05-13 08:44:45 +03007 * Copyright (c) 2014 Paul Sokolovsky
Damien George04b91472014-05-03 23:27:38 +01008 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 */
27
Damien429d7192013-10-04 19:53:11 +010028#include <stdio.h>
Paul Sokolovsky55ca0752014-03-30 17:35:53 +030029#include <string.h>
Damien429d7192013-10-04 19:53:11 +010030#include <assert.h>
31
Paul Sokolovskyf54bcbf2014-05-02 17:47:01 +030032#include "mpconfig.h"
Damience89a212013-10-15 22:25:17 +010033#include "nlr.h"
Damien429d7192013-10-04 19:53:11 +010034#include "misc.h"
Damien George55baff42014-01-21 21:40:13 +000035#include "qstr.h"
Damiend99b0522013-12-21 18:17:45 +000036#include "obj.h"
Damien Georgedf8127a2014-04-13 11:04:33 +010037#include "emitglue.h"
Damien429d7192013-10-04 19:53:11 +010038#include "runtime.h"
Damiend99b0522013-12-21 18:17:45 +000039#include "bc0.h"
Damieneb19efb2013-10-10 22:06:54 +010040#include "bc.h"
Paul Sokolovskycf21a4e2014-03-26 17:36:12 +020041#include "objgenerator.h"
Damien429d7192013-10-04 19:53:11 +010042
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +030043#if 0
Damien George3417bc22014-05-10 10:36:38 +010044#define TRACE(ip) mp_bytecode_print2(ip, 1);
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +030045#else
46#define TRACE(ip)
47#endif
Damien Georgee90be0d2014-04-10 16:21:34 +000048
Paul Sokolovsky85193422014-01-31 19:45:15 +020049// Value stack grows up (this makes it incompatible with native C stack, but
50// makes sure that arguments to functions are in natural order arg1..argN
51// (Python semantics mandates left-to-right evaluation order, including for
52// function arguments). Stack pointer is pre-incremented and points at the
53// top element.
54// Exception stack also grows up, top element is also pointed at.
55
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020056// Exception stack unwind reasons (WHY_* in CPython-speak)
Damien Georgecbddb272014-02-01 20:08:18 +000057// TODO perhaps compress this to RETURN=0, JUMP>0, with number of unwinds
58// left to do encoded in the JUMP number
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020059typedef enum {
60 UNWIND_RETURN = 1,
Damien Georgecbddb272014-02-01 20:08:18 +000061 UNWIND_JUMP,
Paul Sokolovsky6472dea2014-02-01 00:55:05 +020062} mp_unwind_reason_t;
63
Damien Georgedf8127a2014-04-13 11:04:33 +010064#define DECODE_UINT do { \
Paul Sokolovsky0f96ec82014-02-18 21:21:22 +020065 unum = 0; \
66 do { \
67 unum = (unum << 7) + (*ip & 0x7f); \
68 } while ((*ip++ & 0x80) != 0); \
Damien Georgedf8127a2014-04-13 11:04:33 +010069} while (0)
Damien03c9cfb2013-11-05 22:06:08 +000070#define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0)
71#define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0)
Damien Georged8675542014-05-25 22:58:04 +010072#define DECODE_QSTR qstr qst = 0; \
Paul Sokolovsky0f96ec82014-02-18 21:21:22 +020073 do { \
74 qst = (qst << 7) + (*ip & 0x7f); \
Damien Georged8675542014-05-25 22:58:04 +010075 } while ((*ip++ & 0x80) != 0)
Damien Georgedf8127a2014-04-13 11:04:33 +010076#define DECODE_PTR do { \
Damien George40f3c022014-07-03 13:25:24 +010077 ip = (byte*)(((mp_uint_t)ip + sizeof(mp_uint_t) - 1) & (~(sizeof(mp_uint_t) - 1))); /* align ip */ \
78 unum = *(mp_uint_t*)ip; \
79 ip += sizeof(mp_uint_t); \
Damien Georgedf8127a2014-04-13 11:04:33 +010080} while (0)
Damien George20006db2014-01-18 14:10:48 +000081#define PUSH(val) *++sp = (val)
82#define POP() (*sp--)
Damiendb4c3612013-12-10 17:27:24 +000083#define TOP() (*sp)
84#define SET_TOP(val) *sp = (val)
Damien429d7192013-10-04 19:53:11 +010085
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +020086#define PUSH_EXC_BLOCK() \
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +020087 DECODE_ULABEL; /* except labels are always forward */ \
88 ++exc_sp; \
Damien Georgec60a2612014-06-01 12:32:28 +010089 exc_sp->opcode = *code_state->ip; \
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +020090 exc_sp->handler = ip + unum; \
91 exc_sp->val_sp = MP_TAGPTR_MAKE(sp, currently_in_except_block); \
Damien Georged7592a12014-03-30 00:54:48 +000092 exc_sp->prev_exc = MP_OBJ_NULL; \
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +020093 currently_in_except_block = 0; /* in a try block now */
94
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +020095#define POP_EXC_BLOCK() \
96 currently_in_except_block = MP_TAGPTR_TAG(exc_sp->val_sp); /* restore previous state */ \
97 exc_sp--; /* pop back to previous exception handler */
98
Damien George20006db2014-01-18 14:10:48 +000099// fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)
100// sp points to bottom of stack which grows up
Damien Georgec8f78bc2014-02-15 22:55:00 +0000101// returns:
102// MP_VM_RETURN_NORMAL, sp valid, return value in *sp
103// MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
104// MP_VM_RETURN_EXCEPTION, exception in fastn[0]
Damien Georgeaabd83e2014-06-07 14:16:08 +0100105mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_obj_t inject_exc) {
Damien George58ebde42014-05-21 20:32:59 +0100106#if MICROPY_OPT_COMPUTED_GOTO
AZ Huang9413ca02014-04-15 21:29:08 +0800107 #include "vmentrytable.h"
AZ Huang9309d992014-04-15 15:57:01 +0800108 #define DISPATCH() do { \
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +0300109 TRACE(ip); \
Damien Georgec60a2612014-06-01 12:32:28 +0100110 code_state->ip = ip; \
Damien Georgedb128912014-04-27 18:19:06 +0100111 goto *entry_table[*ip++]; \
AZ Huangb1f692e2014-04-14 23:22:44 +0800112 } while(0)
Damien George124df6f2014-10-25 18:19:55 +0100113 #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
AZ Huang9309d992014-04-15 15:57:01 +0800114 #define ENTRY(op) entry_##op
115 #define ENTRY_DEFAULT entry_default
AZ Huangb1f692e2014-04-14 23:22:44 +0800116#else
AZ Huang9309d992014-04-15 15:57:01 +0800117 #define DISPATCH() break
Damien George124df6f2014-10-25 18:19:55 +0100118 #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
AZ Huang9309d992014-04-15 15:57:01 +0800119 #define ENTRY(op) case op
120 #define ENTRY_DEFAULT default
AZ Huangb1f692e2014-04-14 23:22:44 +0800121#endif
122
Damien George66ae8c92014-04-17 16:50:23 +0100123 // nlr_raise needs to be implemented as a goto, so that the C compiler's flow analyser
124 // sees that it's possible for us to jump from the dispatch loop to the exception
125 // handler. Without this, the code may have a different stack layout in the dispatch
126 // loop and the exception handler, leading to very obscure bugs.
127 #define RAISE(o) do { nlr_pop(); nlr.ret_val = o; goto exception_handler; } while(0)
Damien429d7192013-10-04 19:53:11 +0100128
Damien Georgeaabd83e2014-06-07 14:16:08 +0100129 // Pointers which are constant for particular invocation of mp_execute_bytecode()
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300130 mp_obj_t *const fastn = &code_state->state[code_state->n_state - 1];
131 mp_exc_stack_t *const exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
132
Damien George66ae8c92014-04-17 16:50:23 +0100133 // variables that are visible to the exception handler (declared volatile)
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300134 volatile bool currently_in_except_block = MP_TAGPTR_TAG(code_state->exc_sp); // 0 or 1, to detect nested exceptions
135 mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
Damienc9f91972013-10-15 23:46:01 +0100136
Damience89a212013-10-15 22:25:17 +0100137 // outer exception handling loop
Damien429d7192013-10-04 19:53:11 +0100138 for (;;) {
Damien George66ae8c92014-04-17 16:50:23 +0100139 nlr_buf_t nlr;
Damien George9e6e9352014-03-26 18:37:06 +0000140outer_dispatch_loop:
Damience89a212013-10-15 22:25:17 +0100141 if (nlr_push(&nlr) == 0) {
Damien George66ae8c92014-04-17 16:50:23 +0100142 // local variables that are not visible to the exception handler
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300143 const byte *ip = code_state->ip;
144 mp_obj_t *sp = code_state->sp;
Damien George40f3c022014-07-03 13:25:24 +0100145 mp_uint_t unum;
Damien Georged8675542014-05-25 22:58:04 +0100146 mp_obj_t obj_shared;
Damien George66ae8c92014-04-17 16:50:23 +0100147
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200148 // If we have exception to inject, now that we finish setting up
149 // execution context, raise it. This works as if RAISE_VARARGS
150 // bytecode was executed.
Paul Sokolovskycf21a4e2014-03-26 17:36:12 +0200151 // Injecting exc into yield from generator is a special case,
152 // handled by MP_BC_YIELD_FROM itself
153 if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
Damien Georged8675542014-05-25 22:58:04 +0100154 mp_obj_t exc = inject_exc;
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200155 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100156 exc = mp_make_raise_obj(exc);
157 RAISE(exc);
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200158 }
Damien George66ae8c92014-04-17 16:50:23 +0100159
Damience89a212013-10-15 22:25:17 +0100160 // loop to execute byte code
161 for (;;) {
Paul Sokolovsky6472dea2014-02-01 00:55:05 +0200162dispatch_loop:
Damien George58ebde42014-05-21 20:32:59 +0100163#if MICROPY_OPT_COMPUTED_GOTO
AZ Huangb1f692e2014-04-14 23:22:44 +0800164 DISPATCH();
165#else
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +0300166 TRACE(ip);
Damien Georgec60a2612014-06-01 12:32:28 +0100167 code_state->ip = ip;
Damien Georgedb128912014-04-27 18:19:06 +0100168 switch (*ip++) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800169#endif
Damien429d7192013-10-04 19:53:11 +0100170
AZ Huangb1f692e2014-04-14 23:22:44 +0800171 ENTRY(MP_BC_LOAD_CONST_FALSE):
172 PUSH(mp_const_false);
173 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100174
AZ Huangb1f692e2014-04-14 23:22:44 +0800175 ENTRY(MP_BC_LOAD_CONST_NONE):
176 PUSH(mp_const_none);
177 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100178
AZ Huangb1f692e2014-04-14 23:22:44 +0800179 ENTRY(MP_BC_LOAD_CONST_TRUE):
180 PUSH(mp_const_true);
181 DISPATCH();
Damien Georgee9906ac2014-01-04 18:44:46 +0000182
AZ Huangb1f692e2014-04-14 23:22:44 +0800183 ENTRY(MP_BC_LOAD_CONST_ELLIPSIS):
184 PUSH((mp_obj_t)&mp_const_ellipsis_obj);
185 DISPATCH();
186
187 ENTRY(MP_BC_LOAD_CONST_SMALL_INT): {
Damien George40f3c022014-07-03 13:25:24 +0100188 mp_int_t num = 0;
AZ Huangb1f692e2014-04-14 23:22:44 +0800189 if ((ip[0] & 0x40) != 0) {
190 // Number is negative
191 num--;
Paul Sokolovsky047cd402014-02-19 15:47:59 +0200192 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800193 do {
194 num = (num << 7) | (*ip & 0x7f);
195 } while ((*ip++ & 0x80) != 0);
196 PUSH(MP_OBJ_NEW_SMALL_INT(num));
197 DISPATCH();
198 }
Damience89a212013-10-15 22:25:17 +0100199
Damien Georged8675542014-05-25 22:58:04 +0100200 ENTRY(MP_BC_LOAD_CONST_INT): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800201 DECODE_QSTR;
Damien George503d6112014-05-28 14:07:21 +0100202 PUSH(mp_load_const_int(qst));
AZ Huangb1f692e2014-04-14 23:22:44 +0800203 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100204 }
Paul Sokolovskya9f5abd2014-01-17 19:51:46 +0200205
Damien Georged8675542014-05-25 22:58:04 +0100206 ENTRY(MP_BC_LOAD_CONST_DEC): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800207 DECODE_QSTR;
208 PUSH(mp_load_const_dec(qst));
209 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100210 }
Damien7410e442013-11-02 19:47:57 +0000211
Damien Georged8675542014-05-25 22:58:04 +0100212 ENTRY(MP_BC_LOAD_CONST_BYTES): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800213 DECODE_QSTR;
214 PUSH(mp_load_const_bytes(qst));
215 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100216 }
Paul Sokolovskybdf822b2014-01-02 18:46:27 +0200217
Damien Georged8675542014-05-25 22:58:04 +0100218 ENTRY(MP_BC_LOAD_CONST_STRING): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800219 DECODE_QSTR;
220 PUSH(mp_load_const_str(qst));
221 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100222 }
Damience89a212013-10-15 22:25:17 +0100223
AZ Huangb1f692e2014-04-14 23:22:44 +0800224 ENTRY(MP_BC_LOAD_NULL):
225 PUSH(MP_OBJ_NULL);
226 DISPATCH();
Damien George523b5752014-03-31 11:59:23 +0100227
AZ Huangb1f692e2014-04-14 23:22:44 +0800228 ENTRY(MP_BC_LOAD_FAST_N):
229 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100230 obj_shared = fastn[-unum];
AZ Huangb1f692e2014-04-14 23:22:44 +0800231 load_check:
Damien Georged8675542014-05-25 22:58:04 +0100232 if (obj_shared == MP_OBJ_NULL) {
233 local_name_error: {
234 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment");
235 RAISE(obj);
236 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800237 }
Damien Georged8675542014-05-25 22:58:04 +0100238 PUSH(obj_shared);
AZ Huangb1f692e2014-04-14 23:22:44 +0800239 DISPATCH();
Damien George2bf7c092014-04-09 15:26:46 +0100240
AZ Huangb1f692e2014-04-14 23:22:44 +0800241 ENTRY(MP_BC_LOAD_DEREF):
242 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100243 obj_shared = mp_obj_cell_get(fastn[-unum]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800244 goto load_check;
Damien9ecbcff2013-12-11 00:41:43 +0000245
Damien Georged8675542014-05-25 22:58:04 +0100246 ENTRY(MP_BC_LOAD_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800247 DECODE_QSTR;
248 PUSH(mp_load_name(qst));
249 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100250 }
Damience89a212013-10-15 22:25:17 +0100251
Damien Georged8675542014-05-25 22:58:04 +0100252 ENTRY(MP_BC_LOAD_GLOBAL): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800253 DECODE_QSTR;
254 PUSH(mp_load_global(qst));
255 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100256 }
Damience89a212013-10-15 22:25:17 +0100257
Damien Georged8675542014-05-25 22:58:04 +0100258 ENTRY(MP_BC_LOAD_ATTR): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800259 DECODE_QSTR;
260 SET_TOP(mp_load_attr(TOP(), qst));
261 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100262 }
Damience89a212013-10-15 22:25:17 +0100263
Damien Georged8675542014-05-25 22:58:04 +0100264 ENTRY(MP_BC_LOAD_METHOD): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800265 DECODE_QSTR;
266 mp_load_method(*sp, qst, sp);
267 sp += 1;
268 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100269 }
Damience89a212013-10-15 22:25:17 +0100270
AZ Huangb1f692e2014-04-14 23:22:44 +0800271 ENTRY(MP_BC_LOAD_BUILD_CLASS):
272 PUSH(mp_load_build_class());
273 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100274
Damien Georged8675542014-05-25 22:58:04 +0100275 ENTRY(MP_BC_LOAD_SUBSCR): {
276 mp_obj_t index = POP();
277 SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL));
Damien George729f7b42014-04-17 22:10:53 +0100278 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100279 }
Damien George729f7b42014-04-17 22:10:53 +0100280
AZ Huangb1f692e2014-04-14 23:22:44 +0800281 ENTRY(MP_BC_STORE_FAST_N):
282 DECODE_UINT;
283 fastn[-unum] = POP();
284 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100285
AZ Huangb1f692e2014-04-14 23:22:44 +0800286 ENTRY(MP_BC_STORE_DEREF):
287 DECODE_UINT;
288 mp_obj_cell_set(fastn[-unum], POP());
289 DISPATCH();
Damien9ecbcff2013-12-11 00:41:43 +0000290
Damien Georged8675542014-05-25 22:58:04 +0100291 ENTRY(MP_BC_STORE_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800292 DECODE_QSTR;
293 mp_store_name(qst, POP());
294 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100295 }
Damience89a212013-10-15 22:25:17 +0100296
Damien Georged8675542014-05-25 22:58:04 +0100297 ENTRY(MP_BC_STORE_GLOBAL): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800298 DECODE_QSTR;
299 mp_store_global(qst, POP());
300 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100301 }
Damien6addc892013-11-04 23:04:50 +0000302
Damien Georged8675542014-05-25 22:58:04 +0100303 ENTRY(MP_BC_STORE_ATTR): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800304 DECODE_QSTR;
305 mp_store_attr(sp[0], qst, sp[-1]);
306 sp -= 2;
307 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100308 }
Damience89a212013-10-15 22:25:17 +0100309
AZ Huangb1f692e2014-04-14 23:22:44 +0800310 ENTRY(MP_BC_STORE_SUBSCR):
Damien George729f7b42014-04-17 22:10:53 +0100311 mp_obj_subscr(sp[-1], sp[0], sp[-2]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800312 sp -= 3;
313 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100314
AZ Huangb1f692e2014-04-14 23:22:44 +0800315 ENTRY(MP_BC_DELETE_FAST):
316 DECODE_UINT;
317 if (fastn[-unum] == MP_OBJ_NULL) {
318 goto local_name_error;
319 }
320 fastn[-unum] = MP_OBJ_NULL;
321 DISPATCH();
Damien George2bf7c092014-04-09 15:26:46 +0100322
AZ Huangb1f692e2014-04-14 23:22:44 +0800323 ENTRY(MP_BC_DELETE_DEREF):
324 DECODE_UINT;
325 if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
326 goto local_name_error;
327 }
328 mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);
329 DISPATCH();
Damien George2bf7c092014-04-09 15:26:46 +0100330
Damien Georged8675542014-05-25 22:58:04 +0100331 ENTRY(MP_BC_DELETE_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800332 DECODE_QSTR;
333 mp_delete_name(qst);
334 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100335 }
Paul Sokolovskyf9090342014-03-23 21:19:02 +0200336
Damien Georged8675542014-05-25 22:58:04 +0100337 ENTRY(MP_BC_DELETE_GLOBAL): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800338 DECODE_QSTR;
339 mp_delete_global(qst);
340 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100341 }
Damien George1d24ea52014-04-08 21:11:49 +0100342
Damien Georged8675542014-05-25 22:58:04 +0100343 ENTRY(MP_BC_DUP_TOP): {
344 mp_obj_t top = TOP();
345 PUSH(top);
AZ Huangb1f692e2014-04-14 23:22:44 +0800346 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100347 }
Damience89a212013-10-15 22:25:17 +0100348
AZ Huangb1f692e2014-04-14 23:22:44 +0800349 ENTRY(MP_BC_DUP_TOP_TWO):
350 sp += 2;
351 sp[0] = sp[-2];
352 sp[-1] = sp[-3];
353 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100354
AZ Huangb1f692e2014-04-14 23:22:44 +0800355 ENTRY(MP_BC_POP_TOP):
356 sp -= 1;
357 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100358
Damien Georged8675542014-05-25 22:58:04 +0100359 ENTRY(MP_BC_ROT_TWO): {
360 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800361 sp[0] = sp[-1];
Damien Georged8675542014-05-25 22:58:04 +0100362 sp[-1] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800363 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100364 }
Damien4ebb32f2013-11-02 14:33:10 +0000365
Damien Georged8675542014-05-25 22:58:04 +0100366 ENTRY(MP_BC_ROT_THREE): {
367 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800368 sp[0] = sp[-1];
369 sp[-1] = sp[-2];
Damien Georged8675542014-05-25 22:58:04 +0100370 sp[-2] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800371 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100372 }
Damience89a212013-10-15 22:25:17 +0100373
AZ Huangb1f692e2014-04-14 23:22:44 +0800374 ENTRY(MP_BC_JUMP):
375 DECODE_SLABEL;
376 ip += unum;
Damien George124df6f2014-10-25 18:19:55 +0100377 DISPATCH_WITH_PEND_EXC_CHECK();
AZ Huangb1f692e2014-04-14 23:22:44 +0800378
379 ENTRY(MP_BC_POP_JUMP_IF_TRUE):
380 DECODE_SLABEL;
381 if (mp_obj_is_true(POP())) {
Damien03c9cfb2013-11-05 22:06:08 +0000382 ip += unum;
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200383 }
Damien George124df6f2014-10-25 18:19:55 +0100384 DISPATCH_WITH_PEND_EXC_CHECK();
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200385
AZ Huangb1f692e2014-04-14 23:22:44 +0800386 ENTRY(MP_BC_POP_JUMP_IF_FALSE):
387 DECODE_SLABEL;
388 if (!mp_obj_is_true(POP())) {
389 ip += unum;
390 }
Damien George124df6f2014-10-25 18:19:55 +0100391 DISPATCH_WITH_PEND_EXC_CHECK();
Damien George600ae732014-01-21 23:48:04 +0000392
AZ Huangb1f692e2014-04-14 23:22:44 +0800393 ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP):
394 DECODE_SLABEL;
395 if (mp_obj_is_true(TOP())) {
396 ip += unum;
397 } else {
398 sp--;
399 }
Damien George124df6f2014-10-25 18:19:55 +0100400 DISPATCH_WITH_PEND_EXC_CHECK();
Damience89a212013-10-15 22:25:17 +0100401
AZ Huangb1f692e2014-04-14 23:22:44 +0800402 ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP):
403 DECODE_SLABEL;
404 if (mp_obj_is_true(TOP())) {
405 sp--;
406 } else {
407 ip += unum;
408 }
Damien George124df6f2014-10-25 18:19:55 +0100409 DISPATCH_WITH_PEND_EXC_CHECK();
Damience89a212013-10-15 22:25:17 +0100410
Damien Georged8675542014-05-25 22:58:04 +0100411 ENTRY(MP_BC_SETUP_WITH): {
412 mp_obj_t obj = TOP();
413 SET_TOP(mp_load_attr(obj, MP_QSTR___exit__));
414 mp_load_method(obj, MP_QSTR___enter__, sp + 1);
415 mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 1);
AZ Huangb1f692e2014-04-14 23:22:44 +0800416 PUSH_EXC_BLOCK();
Damien Georged8675542014-05-25 22:58:04 +0100417 PUSH(ret);
AZ Huangb1f692e2014-04-14 23:22:44 +0800418 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100419 }
Damience89a212013-10-15 22:25:17 +0100420
AZ Huangb1f692e2014-04-14 23:22:44 +0800421 ENTRY(MP_BC_WITH_CLEANUP): {
422 // Arriving here, there's "exception control block" on top of stack,
423 // and __exit__ bound method underneath it. Bytecode calls __exit__,
424 // and "deletes" it off stack, shifting "exception control block"
425 // to its place.
426 static const mp_obj_t no_exc[] = {mp_const_none, mp_const_none, mp_const_none};
427 if (TOP() == mp_const_none) {
428 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100429 mp_obj_t obj = TOP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800430 SET_TOP(mp_const_none);
Damien Georged8675542014-05-25 22:58:04 +0100431 mp_call_function_n_kw(obj, 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800432 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
433 mp_obj_t cause = POP();
434 switch (MP_OBJ_SMALL_INT_VALUE(cause)) {
435 case UNWIND_RETURN: {
436 mp_obj_t retval = POP();
Damien Georged8675542014-05-25 22:58:04 +0100437 mp_call_function_n_kw(TOP(), 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800438 SET_TOP(retval);
439 PUSH(cause);
440 break;
441 }
442 case UNWIND_JUMP: {
Damien Georged8675542014-05-25 22:58:04 +0100443 mp_call_function_n_kw(sp[-2], 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800444 // Pop __exit__ boundmethod at sp[-2]
445 sp[-2] = sp[-1];
446 sp[-1] = sp[0];
447 SET_TOP(cause);
448 break;
449 }
450 default:
451 assert(0);
452 }
453 } else if (mp_obj_is_exception_type(TOP())) {
454 mp_obj_t args[3] = {sp[0], sp[-1], sp[-2]};
Damien Georged8675542014-05-25 22:58:04 +0100455 mp_obj_t ret_value = mp_call_function_n_kw(sp[-3], 3, 0, args);
AZ Huangb1f692e2014-04-14 23:22:44 +0800456 // Pop __exit__ boundmethod at sp[-3]
Damien Georged8675542014-05-25 22:58:04 +0100457 // TODO: Once semantics is proven, optimize for case when ret_value == True
AZ Huangb1f692e2014-04-14 23:22:44 +0800458 sp[-3] = sp[-2];
459 sp[-2] = sp[-1];
460 sp[-1] = sp[0];
Damien George20006db2014-01-18 14:10:48 +0000461 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100462 if (mp_obj_is_true(ret_value)) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800463 // This is what CPython does
464 //PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_SILENCED));
465 // But what we need to do is - pop exception from value stack...
466 sp -= 3;
467 // ... pop "with" exception handler, and signal END_FINALLY
468 // to just execute finally handler normally (by pushing None
469 // on value stack)
470 assert(exc_sp >= exc_stack);
471 assert(exc_sp->opcode == MP_BC_SETUP_WITH);
472 POP_EXC_BLOCK();
473 PUSH(mp_const_none);
474 }
475 } else {
476 assert(0);
477 }
478 DISPATCH();
479 }
Damienc226dca2013-10-16 16:12:52 +0100480
AZ Huangb1f692e2014-04-14 23:22:44 +0800481 ENTRY(MP_BC_UNWIND_JUMP):
482 DECODE_SLABEL;
483 PUSH((void*)(ip + unum)); // push destination ip for jump
Damien George40f3c022014-07-03 13:25:24 +0100484 PUSH((void*)(mp_uint_t)(*ip)); // push number of exception handlers to unwind (0x80 bit set if we also need to pop stack)
AZ Huangb1f692e2014-04-14 23:22:44 +0800485unwind_jump:
Damien George40f3c022014-07-03 13:25:24 +0100486 unum = (mp_uint_t)POP(); // get number of exception handlers to unwind
Damien George25c84642014-05-30 15:20:41 +0100487 while ((unum & 0x7f) > 0) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800488 unum -= 1;
489 assert(exc_sp >= exc_stack);
490 if (exc_sp->opcode == MP_BC_SETUP_FINALLY || exc_sp->opcode == MP_BC_SETUP_WITH) {
491 // We're going to run "finally" code as a coroutine
492 // (not calling it recursively). Set up a sentinel
493 // on a stack so it can return back to us when it is
494 // done (when END_FINALLY reached).
495 PUSH((void*)unum); // push number of exception handlers left to unwind
496 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
497 ip = exc_sp->handler; // get exception handler byte code address
498 exc_sp--; // pop exception handler
499 goto dispatch_loop; // run the exception handler
500 }
501 exc_sp--;
502 }
503 ip = (const byte*)POP(); // pop destination ip for jump
Damien George25c84642014-05-30 15:20:41 +0100504 if (unum != 0) {
505 sp--;
506 }
Damien George124df6f2014-10-25 18:19:55 +0100507 DISPATCH_WITH_PEND_EXC_CHECK();
Damience89a212013-10-15 22:25:17 +0100508
AZ Huangb1f692e2014-04-14 23:22:44 +0800509 // matched against: POP_BLOCK or POP_EXCEPT (anything else?)
510 ENTRY(MP_BC_SETUP_EXCEPT):
511 ENTRY(MP_BC_SETUP_FINALLY):
512 PUSH_EXC_BLOCK();
513 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100514
AZ Huangb1f692e2014-04-14 23:22:44 +0800515 ENTRY(MP_BC_END_FINALLY):
516 // not fully implemented
517 // if TOS is an exception, reraises the exception (3 values on TOS)
518 // if TOS is None, just pops it and continues
519 // if TOS is an integer, does something else
520 // else error
521 if (mp_obj_is_exception_type(TOP())) {
Damien George66ae8c92014-04-17 16:50:23 +0100522 RAISE(sp[-1]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800523 }
524 if (TOP() == mp_const_none) {
Damien George20006db2014-01-18 14:10:48 +0000525 sp--;
AZ Huangb1f692e2014-04-14 23:22:44 +0800526 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
527 // We finished "finally" coroutine and now dispatch back
528 // to our caller, based on TOS value
529 mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());
530 switch (reason) {
531 case UNWIND_RETURN:
532 goto unwind_return;
533 case UNWIND_JUMP:
534 goto unwind_jump;
535 }
536 assert(0);
537 } else {
538 assert(0);
539 }
540 DISPATCH();
541
542 ENTRY(MP_BC_GET_ITER):
543 SET_TOP(mp_getiter(TOP()));
544 DISPATCH();
545
Damien Georged8675542014-05-25 22:58:04 +0100546 ENTRY(MP_BC_FOR_ITER): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800547 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgec60a2612014-06-01 12:32:28 +0100548 code_state->sp = sp;
Paul Sokolovskyc48d6f72014-05-11 20:32:39 +0300549 assert(TOP());
Damien Georged8675542014-05-25 22:58:04 +0100550 mp_obj_t value = mp_iternext_allow_raise(TOP());
551 if (value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800552 --sp; // pop the exhausted iterator
553 ip += unum; // jump to after for-block
554 } else {
Damien Georged8675542014-05-25 22:58:04 +0100555 PUSH(value); // push the next iteration value
AZ Huangb1f692e2014-04-14 23:22:44 +0800556 }
557 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100558 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800559
560 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
561 ENTRY(MP_BC_POP_BLOCK):
562 // we are exiting an exception handler, so pop the last one of the exception-stack
563 assert(exc_sp >= exc_stack);
564 POP_EXC_BLOCK();
565 DISPATCH();
566
567 // matched against: SETUP_EXCEPT
568 ENTRY(MP_BC_POP_EXCEPT):
569 // TODO need to work out how blocks work etc
570 // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
571 assert(exc_sp >= exc_stack);
572 assert(currently_in_except_block);
573 //sp = (mp_obj_t*)(*exc_sp--);
574 //exc_sp--; // discard ip
575 POP_EXC_BLOCK();
576 //sp -= 3; // pop 3 exception values
577 DISPATCH();
578
579 ENTRY(MP_BC_NOT):
580 if (TOP() == mp_const_true) {
581 SET_TOP(mp_const_false);
582 } else {
583 SET_TOP(mp_const_true);
584 }
585 DISPATCH();
586
AZ Huangb1f692e2014-04-14 23:22:44 +0800587 ENTRY(MP_BC_BUILD_TUPLE):
588 DECODE_UINT;
589 sp -= unum - 1;
590 SET_TOP(mp_obj_new_tuple(unum, sp));
591 DISPATCH();
592
593 ENTRY(MP_BC_BUILD_LIST):
594 DECODE_UINT;
595 sp -= unum - 1;
596 SET_TOP(mp_obj_new_list(unum, sp));
597 DISPATCH();
598
599 ENTRY(MP_BC_LIST_APPEND):
600 DECODE_UINT;
601 // I think it's guaranteed by the compiler that sp[unum] is a list
602 mp_obj_list_append(sp[-unum], sp[0]);
603 sp--;
604 DISPATCH();
605
606 ENTRY(MP_BC_BUILD_MAP):
607 DECODE_UINT;
608 PUSH(mp_obj_new_dict(unum));
609 DISPATCH();
610
611 ENTRY(MP_BC_STORE_MAP):
612 sp -= 2;
613 mp_obj_dict_store(sp[0], sp[2], sp[1]);
614 DISPATCH();
615
616 ENTRY(MP_BC_MAP_ADD):
617 DECODE_UINT;
618 // I think it's guaranteed by the compiler that sp[-unum - 1] is a map
619 mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]);
620 sp -= 2;
621 DISPATCH();
622
Damien George3ebd4d02014-06-01 13:46:47 +0100623#if MICROPY_PY_BUILTINS_SET
AZ Huangb1f692e2014-04-14 23:22:44 +0800624 ENTRY(MP_BC_BUILD_SET):
625 DECODE_UINT;
626 sp -= unum - 1;
627 SET_TOP(mp_obj_new_set(unum, sp));
628 DISPATCH();
629
630 ENTRY(MP_BC_SET_ADD):
631 DECODE_UINT;
632 // I think it's guaranteed by the compiler that sp[-unum] is a set
633 mp_obj_set_store(sp[-unum], sp[0]);
634 sp--;
635 DISPATCH();
Damien George3ebd4d02014-06-01 13:46:47 +0100636#endif
Damienc12aa462013-10-16 20:57:49 +0100637
Damien Georgefb510b32014-06-01 13:32:54 +0100638#if MICROPY_PY_BUILTINS_SLICE
AZ Huangb1f692e2014-04-14 23:22:44 +0800639 ENTRY(MP_BC_BUILD_SLICE):
640 DECODE_UINT;
641 if (unum == 2) {
Damien Georged8675542014-05-25 22:58:04 +0100642 mp_obj_t stop = POP();
643 mp_obj_t start = TOP();
644 SET_TOP(mp_obj_new_slice(start, stop, mp_const_none));
AZ Huangb1f692e2014-04-14 23:22:44 +0800645 } else {
Damien Georged8675542014-05-25 22:58:04 +0100646 mp_obj_t step = POP();
647 mp_obj_t stop = POP();
648 mp_obj_t start = TOP();
649 SET_TOP(mp_obj_new_slice(start, stop, step));
AZ Huangb1f692e2014-04-14 23:22:44 +0800650 }
651 DISPATCH();
652#endif
653
654 ENTRY(MP_BC_UNPACK_SEQUENCE):
655 DECODE_UINT;
656 mp_unpack_sequence(sp[0], unum, sp);
657 sp += unum - 1;
658 DISPATCH();
659
660 ENTRY(MP_BC_UNPACK_EX):
661 DECODE_UINT;
662 mp_unpack_ex(sp[0], unum, sp);
663 sp += (unum & 0xff) + ((unum >> 8) & 0xff);
664 DISPATCH();
665
666 ENTRY(MP_BC_MAKE_FUNCTION):
667 DECODE_PTR;
668 PUSH(mp_make_function_from_raw_code((mp_raw_code_t*)unum, MP_OBJ_NULL, MP_OBJ_NULL));
669 DISPATCH();
670
Damien Georged8675542014-05-25 22:58:04 +0100671 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800672 DECODE_PTR;
673 // Stack layout: def_tuple def_dict <- TOS
Damien Georged8675542014-05-25 22:58:04 +0100674 mp_obj_t def_dict = POP();
675 SET_TOP(mp_make_function_from_raw_code((mp_raw_code_t*)unum, TOP(), def_dict));
AZ Huangb1f692e2014-04-14 23:22:44 +0800676 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100677 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800678
Damien George3558f622014-04-20 17:50:40 +0100679 ENTRY(MP_BC_MAKE_CLOSURE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800680 DECODE_PTR;
Damien George40f3c022014-07-03 13:25:24 +0100681 mp_uint_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100682 // Stack layout: closed_overs <- TOS
683 sp -= n_closed_over - 1;
684 SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800685 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100686 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800687
Damien George3558f622014-04-20 17:50:40 +0100688 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800689 DECODE_PTR;
Damien George40f3c022014-07-03 13:25:24 +0100690 mp_uint_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100691 // Stack layout: def_tuple def_dict closed_overs <- TOS
692 sp -= 2 + n_closed_over - 1;
693 SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, 0x100 | n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800694 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100695 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800696
697 ENTRY(MP_BC_CALL_FUNCTION):
698 DECODE_UINT;
699 // unum & 0xff == n_positional
700 // (unum >> 8) & 0xff == n_keyword
701 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
702 SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
703 DISPATCH();
704
705 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW):
706 DECODE_UINT;
707 // unum & 0xff == n_positional
708 // (unum >> 8) & 0xff == n_keyword
709 // We have folowing stack layout here:
710 // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
711 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
712 SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
713 DISPATCH();
714
715 ENTRY(MP_BC_CALL_METHOD):
716 DECODE_UINT;
717 // unum & 0xff == n_positional
718 // (unum >> 8) & 0xff == n_keyword
719 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
720 SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
721 DISPATCH();
722
723 ENTRY(MP_BC_CALL_METHOD_VAR_KW):
724 DECODE_UINT;
725 // unum & 0xff == n_positional
726 // (unum >> 8) & 0xff == n_keyword
727 // We have folowing stack layout here:
728 // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
729 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
730 SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
731 DISPATCH();
732
733 ENTRY(MP_BC_RETURN_VALUE):
734unwind_return:
735 while (exc_sp >= exc_stack) {
736 if (exc_sp->opcode == MP_BC_SETUP_FINALLY || exc_sp->opcode == MP_BC_SETUP_WITH) {
737 // We're going to run "finally" code as a coroutine
738 // (not calling it recursively). Set up a sentinel
739 // on a stack so it can return back to us when it is
740 // done (when END_FINALLY reached).
741 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
742 ip = exc_sp->handler;
743 // We don't need to do anything with sp, finally is just
744 // syntactic sugar for sequential execution??
745 // sp =
746 exc_sp--;
747 goto dispatch_loop;
748 }
749 exc_sp--;
750 }
751 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300752 code_state->sp = sp;
AZ Huangb1f692e2014-04-14 23:22:44 +0800753 assert(exc_sp == exc_stack - 1);
754 return MP_VM_RETURN_NORMAL;
755
Damien Georged8675542014-05-25 22:58:04 +0100756 ENTRY(MP_BC_RAISE_VARARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800757 unum = *ip++;
Damien Georged8675542014-05-25 22:58:04 +0100758 mp_obj_t obj;
AZ Huangb1f692e2014-04-14 23:22:44 +0800759 assert(unum <= 1);
760 if (unum == 0) {
761 // search for the inner-most previous exception, to reraise it
Damien Georged8675542014-05-25 22:58:04 +0100762 obj = MP_OBJ_NULL;
AZ Huangb1f692e2014-04-14 23:22:44 +0800763 for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
764 if (e->prev_exc != MP_OBJ_NULL) {
Damien Georged8675542014-05-25 22:58:04 +0100765 obj = e->prev_exc;
AZ Huangb1f692e2014-04-14 23:22:44 +0800766 break;
767 }
768 }
Damien Georged8675542014-05-25 22:58:04 +0100769 if (obj == MP_OBJ_NULL) {
770 obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
771 RAISE(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +0800772 }
773 } else {
Damien Georged8675542014-05-25 22:58:04 +0100774 obj = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800775 }
Damien Georged8675542014-05-25 22:58:04 +0100776 obj = mp_make_raise_obj(obj);
777 RAISE(obj);
778 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800779
780 ENTRY(MP_BC_YIELD_VALUE):
781yield:
782 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300783 code_state->ip = ip;
784 code_state->sp = sp;
785 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +0800786 return MP_VM_RETURN_YIELD;
787
788 ENTRY(MP_BC_YIELD_FROM): {
789//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
790#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
Damien George66ae8c92014-04-17 16:50:23 +0100791#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { RAISE(t); }
AZ Huangb1f692e2014-04-14 23:22:44 +0800792 mp_vm_return_kind_t ret_kind;
Damien Georged8675542014-05-25 22:58:04 +0100793 mp_obj_t send_value = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800794 mp_obj_t t_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100795 mp_obj_t ret_value;
AZ Huangb1f692e2014-04-14 23:22:44 +0800796 if (inject_exc != MP_OBJ_NULL) {
797 t_exc = inject_exc;
798 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100799 ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800800 } else {
Damien Georged8675542014-05-25 22:58:04 +0100801 ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800802 }
803
804 if (ret_kind == MP_VM_RETURN_YIELD) {
805 ip--;
Damien Georged8675542014-05-25 22:58:04 +0100806 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800807 goto yield;
808 }
809 if (ret_kind == MP_VM_RETURN_NORMAL) {
810 // Pop exhausted gen
811 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100812 if (ret_value == MP_OBJ_NULL) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800813 // Optimize StopIteration
814 // TODO: get StopIteration's value
815 PUSH(mp_const_none);
816 } else {
Damien Georged8675542014-05-25 22:58:04 +0100817 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800818 }
819
820 // If we injected GeneratorExit downstream, then even
821 // if it was swallowed, we re-raise GeneratorExit
822 GENERATOR_EXIT_IF_NEEDED(t_exc);
823 DISPATCH();
824 }
825 if (ret_kind == MP_VM_RETURN_EXCEPTION) {
826 // Pop exhausted gen
827 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100828 if (EXC_MATCH(ret_value, &mp_type_StopIteration)) {
829 PUSH(mp_obj_exception_get_value(ret_value));
AZ Huangb1f692e2014-04-14 23:22:44 +0800830 // If we injected GeneratorExit downstream, then even
831 // if it was swallowed, we re-raise GeneratorExit
832 GENERATOR_EXIT_IF_NEEDED(t_exc);
833 DISPATCH();
834 } else {
Damien Georged8675542014-05-25 22:58:04 +0100835 RAISE(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800836 }
837 }
Damien429d7192013-10-04 19:53:11 +0100838 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800839
Damien Georged8675542014-05-25 22:58:04 +0100840 ENTRY(MP_BC_IMPORT_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800841 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +0100842 mp_obj_t obj = POP();
843 SET_TOP(mp_import_name(qst, obj, TOP()));
AZ Huangb1f692e2014-04-14 23:22:44 +0800844 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100845 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800846
Damien Georged8675542014-05-25 22:58:04 +0100847 ENTRY(MP_BC_IMPORT_FROM): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800848 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +0100849 mp_obj_t obj = mp_import_from(TOP(), qst);
850 PUSH(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +0800851 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100852 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800853
854 ENTRY(MP_BC_IMPORT_STAR):
855 mp_import_all(POP());
856 DISPATCH();
857
Damien George8456cc02014-10-25 16:43:46 +0100858#if MICROPY_OPT_COMPUTED_GOTO
859 ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):
860 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
861 DISPATCH();
862
863 ENTRY(MP_BC_LOAD_FAST_MULTI):
864 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
865 goto load_check;
866
867 ENTRY(MP_BC_STORE_FAST_MULTI):
868 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
869 DISPATCH();
870
871 ENTRY(MP_BC_UNARY_OP_MULTI):
872 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
873 DISPATCH();
874
875 ENTRY(MP_BC_BINARY_OP_MULTI): {
876 mp_obj_t rhs = POP();
877 mp_obj_t lhs = TOP();
878 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
879 DISPATCH();
880 }
881
882 ENTRY_DEFAULT:
883#else
884 ENTRY_DEFAULT:
885 if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
886 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
887 DISPATCH();
888 } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
889 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
890 goto load_check;
891 } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
892 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
893 DISPATCH();
894 } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 5) {
895 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
896 DISPATCH();
897 } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 35) {
898 mp_obj_t rhs = POP();
899 mp_obj_t lhs = TOP();
900 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
901 DISPATCH();
902 } else
903#endif
904 {
Damien Georged8675542014-05-25 22:58:04 +0100905 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
AZ Huangb1f692e2014-04-14 23:22:44 +0800906 nlr_pop();
Damien Georged8675542014-05-25 22:58:04 +0100907 fastn[0] = obj;
AZ Huangb1f692e2014-04-14 23:22:44 +0800908 return MP_VM_RETURN_EXCEPTION;
Damien Georged8675542014-05-25 22:58:04 +0100909 }
Damien George66ae8c92014-04-17 16:50:23 +0100910
Damien George58ebde42014-05-21 20:32:59 +0100911#if !MICROPY_OPT_COMPUTED_GOTO
AZ Huang9309d992014-04-15 15:57:01 +0800912 } // switch
AZ Huangb1f692e2014-04-14 23:22:44 +0800913#endif
Damien George124df6f2014-10-25 18:19:55 +0100914
915pending_exception_check:
916 if (mp_pending_exception != MP_OBJ_NULL) {
917 mp_obj_t obj = mp_pending_exception;
918 mp_pending_exception = MP_OBJ_NULL;
919 RAISE(obj);
920 }
921 DISPATCH();
922
Damien George66ae8c92014-04-17 16:50:23 +0100923 } // for loop
Damien429d7192013-10-04 19:53:11 +0100924
Damience89a212013-10-15 22:25:17 +0100925 } else {
Damien George66ae8c92014-04-17 16:50:23 +0100926exception_handler:
Damience89a212013-10-15 22:25:17 +0100927 // exception occurred
Damien429d7192013-10-04 19:53:11 +0100928
Damien George9e6e9352014-03-26 18:37:06 +0000929 // check if it's a StopIteration within a for block
Damien Georgec60a2612014-06-01 12:32:28 +0100930 if (*code_state->ip == MP_BC_FOR_ITER && mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) {
931 const byte *ip = code_state->ip + 1;
Damien George40f3c022014-07-03 13:25:24 +0100932 mp_uint_t unum;
Damien George9e6e9352014-03-26 18:37:06 +0000933 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300934 code_state->ip = ip + unum; // jump to after for-block
Damien Georgec60a2612014-06-01 12:32:28 +0100935 code_state->sp -= 1; // pop the exhausted iterator
Damien George9e6e9352014-03-26 18:37:06 +0000936 goto outer_dispatch_loop; // continue with dispatch loop
937 }
938
Damien George08335002014-01-18 23:24:36 +0000939 // set file and line number that the exception occurred at
Paul Sokolovsky382e8ee2014-01-30 13:49:18 +0200940 // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
941 // But consider how to handle nested exceptions.
Damien George6902eed2014-04-04 10:52:59 +0000942 // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
943 if (mp_obj_is_exception_instance(nlr.ret_val) && nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
Damien Georgeb534e1b2014-09-04 14:44:01 +0100944 const byte *ip = code_state->code_info;
945 mp_uint_t code_info_size = mp_decode_uint(&ip);
946 qstr block_name = mp_decode_uint(&ip);
947 qstr source_file = mp_decode_uint(&ip);
948 mp_uint_t bc = code_state->ip - code_state->code_info - code_info_size;
Damien Georgeb427d6a2014-08-26 23:35:57 +0100949 mp_uint_t source_line = 1;
950 mp_uint_t c;
Damien Georgeb534e1b2014-09-04 14:44:01 +0100951 while ((c = *ip)) {
Damien Georgeb427d6a2014-08-26 23:35:57 +0100952 mp_uint_t b, l;
953 if ((c & 0x80) == 0) {
954 // 0b0LLBBBBB encoding
955 b = c & 0x1f;
956 l = c >> 5;
Damien Georgeb534e1b2014-09-04 14:44:01 +0100957 ip += 1;
Damien Georgeb427d6a2014-08-26 23:35:57 +0100958 } else {
959 // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
960 b = c & 0xf;
Damien Georgeb534e1b2014-09-04 14:44:01 +0100961 l = ((c << 4) & 0x700) | ip[1];
962 ip += 2;
Damien Georgeb427d6a2014-08-26 23:35:57 +0100963 }
964 if (bc >= b) {
965 bc -= b;
966 source_line += l;
967 } else {
968 // found source line corresponding to bytecode offset
969 break;
Paul Sokolovsky411732e2014-06-02 18:24:34 +0300970 }
Damien George08335002014-01-18 23:24:36 +0000971 }
Damien George136b1492014-01-19 12:38:49 +0000972 mp_obj_exception_add_traceback(nlr.ret_val, source_file, source_line, block_name);
Damien George08335002014-01-18 23:24:36 +0000973 }
974
Damien8f9e2ee2013-12-29 16:54:59 +0000975 while (currently_in_except_block) {
976 // nested exception
977
Paul Sokolovskyc0abc282014-03-22 13:49:31 +0200978 assert(exc_sp >= exc_stack);
Damien8f9e2ee2013-12-29 16:54:59 +0000979
980 // TODO make a proper message for nested exception
981 // at the moment we are just raising the very last exception (the one that caused the nested exception)
982
983 // move up to previous exception handler
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +0200984 POP_EXC_BLOCK();
Damien8f9e2ee2013-12-29 16:54:59 +0000985 }
986
Paul Sokolovskyc0abc282014-03-22 13:49:31 +0200987 if (exc_sp >= exc_stack) {
Damien8f9e2ee2013-12-29 16:54:59 +0000988 // set flag to indicate that we are now handling an exception
989 currently_in_except_block = 1;
990
Damience89a212013-10-15 22:25:17 +0100991 // catch exception and pass to byte code
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300992 code_state->ip = exc_sp->handler;
Damien George66ae8c92014-04-17 16:50:23 +0100993 mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
Damien Georged7592a12014-03-30 00:54:48 +0000994 // save this exception in the stack so it can be used in a reraise, if needed
995 exc_sp->prev_exc = nlr.ret_val;
Damienc9f91972013-10-15 23:46:01 +0100996 // push(traceback, exc-val, exc-type)
Damiend99b0522013-12-21 18:17:45 +0000997 PUSH(mp_const_none);
Damienc9f91972013-10-15 23:46:01 +0100998 PUSH(nlr.ret_val);
Paul Sokolovsky682f9e62014-03-29 02:52:17 +0200999 PUSH(mp_obj_get_type(nlr.ret_val));
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001000 code_state->sp = sp;
Damien8f9e2ee2013-12-29 16:54:59 +00001001
Damience89a212013-10-15 22:25:17 +01001002 } else {
Damien Georgec8f78bc2014-02-15 22:55:00 +00001003 // propagate exception to higher level
1004 // TODO what to do about ip and sp? they don't really make sense at this point
1005 fastn[0] = nlr.ret_val; // must put exception here because sp is invalid
1006 return MP_VM_RETURN_EXCEPTION;
Damience89a212013-10-15 22:25:17 +01001007 }
Damien429d7192013-10-04 19:53:11 +01001008 }
1009 }
1010}