blob: a2e6a3faf9f5a8101292ead228e2220ef9a861c6 [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 Georgecd97a432014-12-02 19:25:10 +000064#define DECODE_UINT \
65 mp_uint_t unum = 0; \
Paul Sokolovsky0f96ec82014-02-18 21:21:22 +020066 do { \
67 unum = (unum << 7) + (*ip & 0x7f); \
Damien Georgecd97a432014-12-02 19:25:10 +000068 } while ((*ip++ & 0x80) != 0)
69#define DECODE_ULABEL mp_uint_t ulab = (ip[0] | (ip[1] << 8)); ip += 2
70#define DECODE_SLABEL mp_uint_t slab = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2
Damien Georged8675542014-05-25 22:58:04 +010071#define DECODE_QSTR qstr qst = 0; \
Paul Sokolovsky0f96ec82014-02-18 21:21:22 +020072 do { \
73 qst = (qst << 7) + (*ip & 0x7f); \
Damien Georged8675542014-05-25 22:58:04 +010074 } while ((*ip++ & 0x80) != 0)
Damien Georgecd97a432014-12-02 19:25:10 +000075#define DECODE_PTR \
Damien George40f3c022014-07-03 13:25:24 +010076 ip = (byte*)(((mp_uint_t)ip + sizeof(mp_uint_t) - 1) & (~(sizeof(mp_uint_t) - 1))); /* align ip */ \
Damien Georgecd97a432014-12-02 19:25:10 +000077 void *ptr = (void*)*(mp_uint_t*)ip; \
78 ip += sizeof(mp_uint_t)
Damien George20006db2014-01-18 14:10:48 +000079#define PUSH(val) *++sp = (val)
80#define POP() (*sp--)
Damiendb4c3612013-12-10 17:27:24 +000081#define TOP() (*sp)
82#define SET_TOP(val) *sp = (val)
Damien429d7192013-10-04 19:53:11 +010083
Damien Georgecd97a432014-12-02 19:25:10 +000084#define PUSH_EXC_BLOCK() do { \
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +020085 DECODE_ULABEL; /* except labels are always forward */ \
86 ++exc_sp; \
Damien Georgec60a2612014-06-01 12:32:28 +010087 exc_sp->opcode = *code_state->ip; \
Damien Georgecd97a432014-12-02 19:25:10 +000088 exc_sp->handler = ip + ulab; \
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +020089 exc_sp->val_sp = MP_TAGPTR_MAKE(sp, currently_in_except_block); \
Damien Georged7592a12014-03-30 00:54:48 +000090 exc_sp->prev_exc = MP_OBJ_NULL; \
Damien Georgecd97a432014-12-02 19:25:10 +000091 currently_in_except_block = 0; /* in a try block now */ \
92} while (0)
Paul Sokolovsky4fff26a2014-03-29 02:49:07 +020093
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +020094#define POP_EXC_BLOCK() \
95 currently_in_except_block = MP_TAGPTR_TAG(exc_sp->val_sp); /* restore previous state */ \
96 exc_sp--; /* pop back to previous exception handler */
97
Damien George20006db2014-01-18 14:10:48 +000098// fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)
99// sp points to bottom of stack which grows up
Damien Georgec8f78bc2014-02-15 22:55:00 +0000100// returns:
101// MP_VM_RETURN_NORMAL, sp valid, return value in *sp
102// MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
103// MP_VM_RETURN_EXCEPTION, exception in fastn[0]
Damien Georgeaabd83e2014-06-07 14:16:08 +0100104mp_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 +0100105#if MICROPY_OPT_COMPUTED_GOTO
AZ Huang9413ca02014-04-15 21:29:08 +0800106 #include "vmentrytable.h"
AZ Huang9309d992014-04-15 15:57:01 +0800107 #define DISPATCH() do { \
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +0300108 TRACE(ip); \
Damien Georgec60a2612014-06-01 12:32:28 +0100109 code_state->ip = ip; \
Damien Georgedb128912014-04-27 18:19:06 +0100110 goto *entry_table[*ip++]; \
AZ Huangb1f692e2014-04-14 23:22:44 +0800111 } while(0)
Damien George124df6f2014-10-25 18:19:55 +0100112 #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
AZ Huang9309d992014-04-15 15:57:01 +0800113 #define ENTRY(op) entry_##op
114 #define ENTRY_DEFAULT entry_default
AZ Huangb1f692e2014-04-14 23:22:44 +0800115#else
AZ Huang9309d992014-04-15 15:57:01 +0800116 #define DISPATCH() break
Damien George124df6f2014-10-25 18:19:55 +0100117 #define DISPATCH_WITH_PEND_EXC_CHECK() goto pending_exception_check
AZ Huang9309d992014-04-15 15:57:01 +0800118 #define ENTRY(op) case op
119 #define ENTRY_DEFAULT default
AZ Huangb1f692e2014-04-14 23:22:44 +0800120#endif
121
Damien George66ae8c92014-04-17 16:50:23 +0100122 // nlr_raise needs to be implemented as a goto, so that the C compiler's flow analyser
123 // sees that it's possible for us to jump from the dispatch loop to the exception
124 // handler. Without this, the code may have a different stack layout in the dispatch
125 // loop and the exception handler, leading to very obscure bugs.
126 #define RAISE(o) do { nlr_pop(); nlr.ret_val = o; goto exception_handler; } while(0)
Damien429d7192013-10-04 19:53:11 +0100127
Damien Georgeaabd83e2014-06-07 14:16:08 +0100128 // Pointers which are constant for particular invocation of mp_execute_bytecode()
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300129 mp_obj_t *const fastn = &code_state->state[code_state->n_state - 1];
130 mp_exc_stack_t *const exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
131
Damien George66ae8c92014-04-17 16:50:23 +0100132 // variables that are visible to the exception handler (declared volatile)
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300133 volatile bool currently_in_except_block = MP_TAGPTR_TAG(code_state->exc_sp); // 0 or 1, to detect nested exceptions
134 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 +0100135
Damience89a212013-10-15 22:25:17 +0100136 // outer exception handling loop
Damien429d7192013-10-04 19:53:11 +0100137 for (;;) {
Damien George66ae8c92014-04-17 16:50:23 +0100138 nlr_buf_t nlr;
Damien George9e6e9352014-03-26 18:37:06 +0000139outer_dispatch_loop:
Damience89a212013-10-15 22:25:17 +0100140 if (nlr_push(&nlr) == 0) {
Damien George66ae8c92014-04-17 16:50:23 +0100141 // local variables that are not visible to the exception handler
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300142 const byte *ip = code_state->ip;
143 mp_obj_t *sp = code_state->sp;
Damien Georged8675542014-05-25 22:58:04 +0100144 mp_obj_t obj_shared;
Damien George66ae8c92014-04-17 16:50:23 +0100145
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200146 // If we have exception to inject, now that we finish setting up
147 // execution context, raise it. This works as if RAISE_VARARGS
148 // bytecode was executed.
Paul Sokolovskycf21a4e2014-03-26 17:36:12 +0200149 // Injecting exc into yield from generator is a special case,
150 // handled by MP_BC_YIELD_FROM itself
151 if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
Damien Georged8675542014-05-25 22:58:04 +0100152 mp_obj_t exc = inject_exc;
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200153 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100154 exc = mp_make_raise_obj(exc);
155 RAISE(exc);
Paul Sokolovsky48caa092014-03-22 17:50:12 +0200156 }
Damien George66ae8c92014-04-17 16:50:23 +0100157
Damience89a212013-10-15 22:25:17 +0100158 // loop to execute byte code
159 for (;;) {
Paul Sokolovsky6472dea2014-02-01 00:55:05 +0200160dispatch_loop:
Damien George58ebde42014-05-21 20:32:59 +0100161#if MICROPY_OPT_COMPUTED_GOTO
AZ Huangb1f692e2014-04-14 23:22:44 +0800162 DISPATCH();
163#else
Paul Sokolovskyc5e32c62014-04-23 03:40:24 +0300164 TRACE(ip);
Damien Georgec60a2612014-06-01 12:32:28 +0100165 code_state->ip = ip;
Damien Georgedb128912014-04-27 18:19:06 +0100166 switch (*ip++) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800167#endif
Damien429d7192013-10-04 19:53:11 +0100168
AZ Huangb1f692e2014-04-14 23:22:44 +0800169 ENTRY(MP_BC_LOAD_CONST_FALSE):
170 PUSH(mp_const_false);
171 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100172
AZ Huangb1f692e2014-04-14 23:22:44 +0800173 ENTRY(MP_BC_LOAD_CONST_NONE):
174 PUSH(mp_const_none);
175 DISPATCH();
Damien429d7192013-10-04 19:53:11 +0100176
AZ Huangb1f692e2014-04-14 23:22:44 +0800177 ENTRY(MP_BC_LOAD_CONST_TRUE):
178 PUSH(mp_const_true);
179 DISPATCH();
Damien Georgee9906ac2014-01-04 18:44:46 +0000180
AZ Huangb1f692e2014-04-14 23:22:44 +0800181 ENTRY(MP_BC_LOAD_CONST_ELLIPSIS):
182 PUSH((mp_obj_t)&mp_const_ellipsis_obj);
183 DISPATCH();
184
185 ENTRY(MP_BC_LOAD_CONST_SMALL_INT): {
Damien George40f3c022014-07-03 13:25:24 +0100186 mp_int_t num = 0;
AZ Huangb1f692e2014-04-14 23:22:44 +0800187 if ((ip[0] & 0x40) != 0) {
188 // Number is negative
189 num--;
Paul Sokolovsky047cd402014-02-19 15:47:59 +0200190 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800191 do {
192 num = (num << 7) | (*ip & 0x7f);
193 } while ((*ip++ & 0x80) != 0);
194 PUSH(MP_OBJ_NEW_SMALL_INT(num));
195 DISPATCH();
196 }
Damience89a212013-10-15 22:25:17 +0100197
Damien Georged8675542014-05-25 22:58:04 +0100198 ENTRY(MP_BC_LOAD_CONST_INT): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800199 DECODE_QSTR;
Damien George503d6112014-05-28 14:07:21 +0100200 PUSH(mp_load_const_int(qst));
AZ Huangb1f692e2014-04-14 23:22:44 +0800201 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100202 }
Paul Sokolovskya9f5abd2014-01-17 19:51:46 +0200203
Damien Georged8675542014-05-25 22:58:04 +0100204 ENTRY(MP_BC_LOAD_CONST_DEC): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800205 DECODE_QSTR;
206 PUSH(mp_load_const_dec(qst));
207 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100208 }
Damien7410e442013-11-02 19:47:57 +0000209
Damien Georged8675542014-05-25 22:58:04 +0100210 ENTRY(MP_BC_LOAD_CONST_BYTES): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800211 DECODE_QSTR;
212 PUSH(mp_load_const_bytes(qst));
213 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100214 }
Paul Sokolovskybdf822b2014-01-02 18:46:27 +0200215
Damien Georged8675542014-05-25 22:58:04 +0100216 ENTRY(MP_BC_LOAD_CONST_STRING): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800217 DECODE_QSTR;
218 PUSH(mp_load_const_str(qst));
219 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100220 }
Damience89a212013-10-15 22:25:17 +0100221
AZ Huangb1f692e2014-04-14 23:22:44 +0800222 ENTRY(MP_BC_LOAD_NULL):
223 PUSH(MP_OBJ_NULL);
224 DISPATCH();
Damien George523b5752014-03-31 11:59:23 +0100225
Damien Georgecd97a432014-12-02 19:25:10 +0000226 ENTRY(MP_BC_LOAD_FAST_N): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800227 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100228 obj_shared = fastn[-unum];
AZ Huangb1f692e2014-04-14 23:22:44 +0800229 load_check:
Damien Georged8675542014-05-25 22:58:04 +0100230 if (obj_shared == MP_OBJ_NULL) {
231 local_name_error: {
232 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment");
233 RAISE(obj);
234 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800235 }
Damien Georged8675542014-05-25 22:58:04 +0100236 PUSH(obj_shared);
AZ Huangb1f692e2014-04-14 23:22:44 +0800237 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000238 }
Damien George2bf7c092014-04-09 15:26:46 +0100239
Damien Georgecd97a432014-12-02 19:25:10 +0000240 ENTRY(MP_BC_LOAD_DEREF): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800241 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100242 obj_shared = mp_obj_cell_get(fastn[-unum]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800243 goto load_check;
Damien Georgecd97a432014-12-02 19:25:10 +0000244 }
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
Damien Georgecd97a432014-12-02 19:25:10 +0000281 ENTRY(MP_BC_STORE_FAST_N): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800282 DECODE_UINT;
283 fastn[-unum] = POP();
284 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000285 }
Damience89a212013-10-15 22:25:17 +0100286
Damien Georgecd97a432014-12-02 19:25:10 +0000287 ENTRY(MP_BC_STORE_DEREF): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800288 DECODE_UINT;
289 mp_obj_cell_set(fastn[-unum], POP());
290 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000291 }
Damien9ecbcff2013-12-11 00:41:43 +0000292
Damien Georged8675542014-05-25 22:58:04 +0100293 ENTRY(MP_BC_STORE_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800294 DECODE_QSTR;
295 mp_store_name(qst, POP());
296 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100297 }
Damience89a212013-10-15 22:25:17 +0100298
Damien Georged8675542014-05-25 22:58:04 +0100299 ENTRY(MP_BC_STORE_GLOBAL): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800300 DECODE_QSTR;
301 mp_store_global(qst, POP());
302 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100303 }
Damien6addc892013-11-04 23:04:50 +0000304
Damien Georged8675542014-05-25 22:58:04 +0100305 ENTRY(MP_BC_STORE_ATTR): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800306 DECODE_QSTR;
307 mp_store_attr(sp[0], qst, sp[-1]);
308 sp -= 2;
309 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100310 }
Damience89a212013-10-15 22:25:17 +0100311
AZ Huangb1f692e2014-04-14 23:22:44 +0800312 ENTRY(MP_BC_STORE_SUBSCR):
Damien George729f7b42014-04-17 22:10:53 +0100313 mp_obj_subscr(sp[-1], sp[0], sp[-2]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800314 sp -= 3;
315 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100316
Damien Georgecd97a432014-12-02 19:25:10 +0000317 ENTRY(MP_BC_DELETE_FAST): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800318 DECODE_UINT;
319 if (fastn[-unum] == MP_OBJ_NULL) {
320 goto local_name_error;
321 }
322 fastn[-unum] = MP_OBJ_NULL;
323 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000324 }
Damien George2bf7c092014-04-09 15:26:46 +0100325
Damien Georgecd97a432014-12-02 19:25:10 +0000326 ENTRY(MP_BC_DELETE_DEREF): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800327 DECODE_UINT;
328 if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
329 goto local_name_error;
330 }
331 mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);
332 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000333 }
Damien George2bf7c092014-04-09 15:26:46 +0100334
Damien Georged8675542014-05-25 22:58:04 +0100335 ENTRY(MP_BC_DELETE_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800336 DECODE_QSTR;
337 mp_delete_name(qst);
338 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100339 }
Paul Sokolovskyf9090342014-03-23 21:19:02 +0200340
Damien Georged8675542014-05-25 22:58:04 +0100341 ENTRY(MP_BC_DELETE_GLOBAL): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800342 DECODE_QSTR;
343 mp_delete_global(qst);
344 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100345 }
Damien George1d24ea52014-04-08 21:11:49 +0100346
Damien Georged8675542014-05-25 22:58:04 +0100347 ENTRY(MP_BC_DUP_TOP): {
348 mp_obj_t top = TOP();
349 PUSH(top);
AZ Huangb1f692e2014-04-14 23:22:44 +0800350 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100351 }
Damience89a212013-10-15 22:25:17 +0100352
AZ Huangb1f692e2014-04-14 23:22:44 +0800353 ENTRY(MP_BC_DUP_TOP_TWO):
354 sp += 2;
355 sp[0] = sp[-2];
356 sp[-1] = sp[-3];
357 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100358
AZ Huangb1f692e2014-04-14 23:22:44 +0800359 ENTRY(MP_BC_POP_TOP):
360 sp -= 1;
361 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100362
Damien Georged8675542014-05-25 22:58:04 +0100363 ENTRY(MP_BC_ROT_TWO): {
364 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800365 sp[0] = sp[-1];
Damien Georged8675542014-05-25 22:58:04 +0100366 sp[-1] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800367 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100368 }
Damien4ebb32f2013-11-02 14:33:10 +0000369
Damien Georged8675542014-05-25 22:58:04 +0100370 ENTRY(MP_BC_ROT_THREE): {
371 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800372 sp[0] = sp[-1];
373 sp[-1] = sp[-2];
Damien Georged8675542014-05-25 22:58:04 +0100374 sp[-2] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800375 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100376 }
Damience89a212013-10-15 22:25:17 +0100377
Damien Georgecd97a432014-12-02 19:25:10 +0000378 ENTRY(MP_BC_JUMP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800379 DECODE_SLABEL;
Damien Georgecd97a432014-12-02 19:25:10 +0000380 ip += slab;
Damien George124df6f2014-10-25 18:19:55 +0100381 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000382 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800383
Damien Georgecd97a432014-12-02 19:25:10 +0000384 ENTRY(MP_BC_POP_JUMP_IF_TRUE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800385 DECODE_SLABEL;
386 if (mp_obj_is_true(POP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000387 ip += slab;
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200388 }
Damien George124df6f2014-10-25 18:19:55 +0100389 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000390 }
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200391
Damien Georgecd97a432014-12-02 19:25:10 +0000392 ENTRY(MP_BC_POP_JUMP_IF_FALSE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800393 DECODE_SLABEL;
394 if (!mp_obj_is_true(POP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000395 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800396 }
Damien George124df6f2014-10-25 18:19:55 +0100397 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000398 }
Damien George600ae732014-01-21 23:48:04 +0000399
Damien Georgecd97a432014-12-02 19:25:10 +0000400 ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800401 DECODE_SLABEL;
402 if (mp_obj_is_true(TOP())) {
Damien Georgecd97a432014-12-02 19:25:10 +0000403 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800404 } else {
405 sp--;
406 }
Damien George124df6f2014-10-25 18:19:55 +0100407 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000408 }
Damience89a212013-10-15 22:25:17 +0100409
Damien Georgecd97a432014-12-02 19:25:10 +0000410 ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800411 DECODE_SLABEL;
412 if (mp_obj_is_true(TOP())) {
413 sp--;
414 } else {
Damien Georgecd97a432014-12-02 19:25:10 +0000415 ip += slab;
AZ Huangb1f692e2014-04-14 23:22:44 +0800416 }
Damien George124df6f2014-10-25 18:19:55 +0100417 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000418 }
Damience89a212013-10-15 22:25:17 +0100419
Damien Georged8675542014-05-25 22:58:04 +0100420 ENTRY(MP_BC_SETUP_WITH): {
421 mp_obj_t obj = TOP();
422 SET_TOP(mp_load_attr(obj, MP_QSTR___exit__));
423 mp_load_method(obj, MP_QSTR___enter__, sp + 1);
424 mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 1);
AZ Huangb1f692e2014-04-14 23:22:44 +0800425 PUSH_EXC_BLOCK();
Damien Georged8675542014-05-25 22:58:04 +0100426 PUSH(ret);
AZ Huangb1f692e2014-04-14 23:22:44 +0800427 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100428 }
Damience89a212013-10-15 22:25:17 +0100429
AZ Huangb1f692e2014-04-14 23:22:44 +0800430 ENTRY(MP_BC_WITH_CLEANUP): {
431 // Arriving here, there's "exception control block" on top of stack,
432 // and __exit__ bound method underneath it. Bytecode calls __exit__,
433 // and "deletes" it off stack, shifting "exception control block"
434 // to its place.
435 static const mp_obj_t no_exc[] = {mp_const_none, mp_const_none, mp_const_none};
436 if (TOP() == mp_const_none) {
437 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100438 mp_obj_t obj = TOP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800439 SET_TOP(mp_const_none);
Damien Georged8675542014-05-25 22:58:04 +0100440 mp_call_function_n_kw(obj, 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800441 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
442 mp_obj_t cause = POP();
443 switch (MP_OBJ_SMALL_INT_VALUE(cause)) {
444 case UNWIND_RETURN: {
445 mp_obj_t retval = POP();
Damien Georged8675542014-05-25 22:58:04 +0100446 mp_call_function_n_kw(TOP(), 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800447 SET_TOP(retval);
448 PUSH(cause);
449 break;
450 }
451 case UNWIND_JUMP: {
Damien Georged8675542014-05-25 22:58:04 +0100452 mp_call_function_n_kw(sp[-2], 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800453 // Pop __exit__ boundmethod at sp[-2]
454 sp[-2] = sp[-1];
455 sp[-1] = sp[0];
456 SET_TOP(cause);
457 break;
458 }
459 default:
460 assert(0);
461 }
462 } else if (mp_obj_is_exception_type(TOP())) {
463 mp_obj_t args[3] = {sp[0], sp[-1], sp[-2]};
Damien Georged8675542014-05-25 22:58:04 +0100464 mp_obj_t ret_value = mp_call_function_n_kw(sp[-3], 3, 0, args);
AZ Huangb1f692e2014-04-14 23:22:44 +0800465 // Pop __exit__ boundmethod at sp[-3]
Damien Georged8675542014-05-25 22:58:04 +0100466 // TODO: Once semantics is proven, optimize for case when ret_value == True
AZ Huangb1f692e2014-04-14 23:22:44 +0800467 sp[-3] = sp[-2];
468 sp[-2] = sp[-1];
469 sp[-1] = sp[0];
Damien George20006db2014-01-18 14:10:48 +0000470 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100471 if (mp_obj_is_true(ret_value)) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800472 // This is what CPython does
473 //PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_SILENCED));
474 // But what we need to do is - pop exception from value stack...
475 sp -= 3;
476 // ... pop "with" exception handler, and signal END_FINALLY
477 // to just execute finally handler normally (by pushing None
478 // on value stack)
479 assert(exc_sp >= exc_stack);
480 assert(exc_sp->opcode == MP_BC_SETUP_WITH);
481 POP_EXC_BLOCK();
482 PUSH(mp_const_none);
483 }
484 } else {
485 assert(0);
486 }
487 DISPATCH();
488 }
Damienc226dca2013-10-16 16:12:52 +0100489
Damien Georgecd97a432014-12-02 19:25:10 +0000490 ENTRY(MP_BC_UNWIND_JUMP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800491 DECODE_SLABEL;
Damien Georgecd97a432014-12-02 19:25:10 +0000492 PUSH((void*)(ip + slab)); // push destination ip for jump
Damien George40f3c022014-07-03 13:25:24 +0100493 PUSH((void*)(mp_uint_t)(*ip)); // push number of exception handlers to unwind (0x80 bit set if we also need to pop stack)
Damien Georgecd97a432014-12-02 19:25:10 +0000494unwind_jump:;
495 mp_uint_t unum = (mp_uint_t)POP(); // get number of exception handlers to unwind
Damien George25c84642014-05-30 15:20:41 +0100496 while ((unum & 0x7f) > 0) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800497 unum -= 1;
498 assert(exc_sp >= exc_stack);
499 if (exc_sp->opcode == MP_BC_SETUP_FINALLY || exc_sp->opcode == MP_BC_SETUP_WITH) {
500 // We're going to run "finally" code as a coroutine
501 // (not calling it recursively). Set up a sentinel
502 // on a stack so it can return back to us when it is
503 // done (when END_FINALLY reached).
504 PUSH((void*)unum); // push number of exception handlers left to unwind
505 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
506 ip = exc_sp->handler; // get exception handler byte code address
507 exc_sp--; // pop exception handler
508 goto dispatch_loop; // run the exception handler
509 }
510 exc_sp--;
511 }
512 ip = (const byte*)POP(); // pop destination ip for jump
Damien George25c84642014-05-30 15:20:41 +0100513 if (unum != 0) {
514 sp--;
515 }
Damien George124df6f2014-10-25 18:19:55 +0100516 DISPATCH_WITH_PEND_EXC_CHECK();
Damien Georgecd97a432014-12-02 19:25:10 +0000517 }
Damience89a212013-10-15 22:25:17 +0100518
AZ Huangb1f692e2014-04-14 23:22:44 +0800519 // matched against: POP_BLOCK or POP_EXCEPT (anything else?)
520 ENTRY(MP_BC_SETUP_EXCEPT):
Damien Georgecd97a432014-12-02 19:25:10 +0000521 ENTRY(MP_BC_SETUP_FINALLY): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800522 PUSH_EXC_BLOCK();
523 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000524 }
Damience89a212013-10-15 22:25:17 +0100525
AZ Huangb1f692e2014-04-14 23:22:44 +0800526 ENTRY(MP_BC_END_FINALLY):
527 // not fully implemented
528 // if TOS is an exception, reraises the exception (3 values on TOS)
529 // if TOS is None, just pops it and continues
530 // if TOS is an integer, does something else
531 // else error
532 if (mp_obj_is_exception_type(TOP())) {
Damien George66ae8c92014-04-17 16:50:23 +0100533 RAISE(sp[-1]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800534 }
535 if (TOP() == mp_const_none) {
Damien George20006db2014-01-18 14:10:48 +0000536 sp--;
AZ Huangb1f692e2014-04-14 23:22:44 +0800537 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
538 // We finished "finally" coroutine and now dispatch back
539 // to our caller, based on TOS value
540 mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());
541 switch (reason) {
542 case UNWIND_RETURN:
543 goto unwind_return;
544 case UNWIND_JUMP:
545 goto unwind_jump;
546 }
547 assert(0);
548 } else {
549 assert(0);
550 }
551 DISPATCH();
552
553 ENTRY(MP_BC_GET_ITER):
554 SET_TOP(mp_getiter(TOP()));
555 DISPATCH();
556
Damien Georged8675542014-05-25 22:58:04 +0100557 ENTRY(MP_BC_FOR_ITER): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800558 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgec60a2612014-06-01 12:32:28 +0100559 code_state->sp = sp;
Paul Sokolovskyc48d6f72014-05-11 20:32:39 +0300560 assert(TOP());
Damien Georged8675542014-05-25 22:58:04 +0100561 mp_obj_t value = mp_iternext_allow_raise(TOP());
562 if (value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800563 --sp; // pop the exhausted iterator
Damien Georgecd97a432014-12-02 19:25:10 +0000564 ip += ulab; // jump to after for-block
AZ Huangb1f692e2014-04-14 23:22:44 +0800565 } else {
Damien Georged8675542014-05-25 22:58:04 +0100566 PUSH(value); // push the next iteration value
AZ Huangb1f692e2014-04-14 23:22:44 +0800567 }
568 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100569 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800570
571 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
572 ENTRY(MP_BC_POP_BLOCK):
573 // we are exiting an exception handler, so pop the last one of the exception-stack
574 assert(exc_sp >= exc_stack);
575 POP_EXC_BLOCK();
576 DISPATCH();
577
578 // matched against: SETUP_EXCEPT
579 ENTRY(MP_BC_POP_EXCEPT):
580 // TODO need to work out how blocks work etc
581 // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
582 assert(exc_sp >= exc_stack);
583 assert(currently_in_except_block);
584 //sp = (mp_obj_t*)(*exc_sp--);
585 //exc_sp--; // discard ip
586 POP_EXC_BLOCK();
587 //sp -= 3; // pop 3 exception values
588 DISPATCH();
589
590 ENTRY(MP_BC_NOT):
591 if (TOP() == mp_const_true) {
592 SET_TOP(mp_const_false);
593 } else {
594 SET_TOP(mp_const_true);
595 }
596 DISPATCH();
597
Damien Georgecd97a432014-12-02 19:25:10 +0000598 ENTRY(MP_BC_BUILD_TUPLE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800599 DECODE_UINT;
600 sp -= unum - 1;
601 SET_TOP(mp_obj_new_tuple(unum, sp));
602 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000603 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800604
Damien Georgecd97a432014-12-02 19:25:10 +0000605 ENTRY(MP_BC_BUILD_LIST): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800606 DECODE_UINT;
607 sp -= unum - 1;
608 SET_TOP(mp_obj_new_list(unum, sp));
609 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000610 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800611
Damien Georgecd97a432014-12-02 19:25:10 +0000612 ENTRY(MP_BC_LIST_APPEND): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800613 DECODE_UINT;
614 // I think it's guaranteed by the compiler that sp[unum] is a list
615 mp_obj_list_append(sp[-unum], sp[0]);
616 sp--;
617 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000618 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800619
Damien Georgecd97a432014-12-02 19:25:10 +0000620 ENTRY(MP_BC_BUILD_MAP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800621 DECODE_UINT;
622 PUSH(mp_obj_new_dict(unum));
623 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000624 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800625
626 ENTRY(MP_BC_STORE_MAP):
627 sp -= 2;
628 mp_obj_dict_store(sp[0], sp[2], sp[1]);
629 DISPATCH();
630
Damien Georgecd97a432014-12-02 19:25:10 +0000631 ENTRY(MP_BC_MAP_ADD): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800632 DECODE_UINT;
633 // I think it's guaranteed by the compiler that sp[-unum - 1] is a map
634 mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]);
635 sp -= 2;
636 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000637 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800638
Damien George3ebd4d02014-06-01 13:46:47 +0100639#if MICROPY_PY_BUILTINS_SET
Damien Georgecd97a432014-12-02 19:25:10 +0000640 ENTRY(MP_BC_BUILD_SET): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800641 DECODE_UINT;
642 sp -= unum - 1;
643 SET_TOP(mp_obj_new_set(unum, sp));
644 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000645 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800646
Damien Georgecd97a432014-12-02 19:25:10 +0000647 ENTRY(MP_BC_SET_ADD): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800648 DECODE_UINT;
649 // I think it's guaranteed by the compiler that sp[-unum] is a set
650 mp_obj_set_store(sp[-unum], sp[0]);
651 sp--;
652 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000653 }
Damien George3ebd4d02014-06-01 13:46:47 +0100654#endif
Damienc12aa462013-10-16 20:57:49 +0100655
Damien Georgefb510b32014-06-01 13:32:54 +0100656#if MICROPY_PY_BUILTINS_SLICE
Damien Georgecd97a432014-12-02 19:25:10 +0000657 ENTRY(MP_BC_BUILD_SLICE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800658 DECODE_UINT;
659 if (unum == 2) {
Damien Georged8675542014-05-25 22:58:04 +0100660 mp_obj_t stop = POP();
661 mp_obj_t start = TOP();
662 SET_TOP(mp_obj_new_slice(start, stop, mp_const_none));
AZ Huangb1f692e2014-04-14 23:22:44 +0800663 } else {
Damien Georged8675542014-05-25 22:58:04 +0100664 mp_obj_t step = POP();
665 mp_obj_t stop = POP();
666 mp_obj_t start = TOP();
667 SET_TOP(mp_obj_new_slice(start, stop, step));
AZ Huangb1f692e2014-04-14 23:22:44 +0800668 }
669 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000670 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800671#endif
672
Damien Georgecd97a432014-12-02 19:25:10 +0000673 ENTRY(MP_BC_UNPACK_SEQUENCE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800674 DECODE_UINT;
675 mp_unpack_sequence(sp[0], unum, sp);
676 sp += unum - 1;
677 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000678 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800679
Damien Georgecd97a432014-12-02 19:25:10 +0000680 ENTRY(MP_BC_UNPACK_EX): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800681 DECODE_UINT;
682 mp_unpack_ex(sp[0], unum, sp);
683 sp += (unum & 0xff) + ((unum >> 8) & 0xff);
684 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000685 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800686
Damien Georgecd97a432014-12-02 19:25:10 +0000687 ENTRY(MP_BC_MAKE_FUNCTION): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800688 DECODE_PTR;
Damien Georgecd97a432014-12-02 19:25:10 +0000689 PUSH(mp_make_function_from_raw_code(ptr, MP_OBJ_NULL, MP_OBJ_NULL));
AZ Huangb1f692e2014-04-14 23:22:44 +0800690 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000691 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800692
Damien Georged8675542014-05-25 22:58:04 +0100693 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800694 DECODE_PTR;
695 // Stack layout: def_tuple def_dict <- TOS
Damien Georged8675542014-05-25 22:58:04 +0100696 mp_obj_t def_dict = POP();
Damien Georgecd97a432014-12-02 19:25:10 +0000697 SET_TOP(mp_make_function_from_raw_code(ptr, TOP(), def_dict));
AZ Huangb1f692e2014-04-14 23:22:44 +0800698 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100699 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800700
Damien George3558f622014-04-20 17:50:40 +0100701 ENTRY(MP_BC_MAKE_CLOSURE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800702 DECODE_PTR;
Damien George40f3c022014-07-03 13:25:24 +0100703 mp_uint_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100704 // Stack layout: closed_overs <- TOS
705 sp -= n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000706 SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800707 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100708 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800709
Damien George3558f622014-04-20 17:50:40 +0100710 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800711 DECODE_PTR;
Damien George40f3c022014-07-03 13:25:24 +0100712 mp_uint_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100713 // Stack layout: def_tuple def_dict closed_overs <- TOS
714 sp -= 2 + n_closed_over - 1;
Damien Georgecd97a432014-12-02 19:25:10 +0000715 SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800716 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100717 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800718
Damien Georgecd97a432014-12-02 19:25:10 +0000719 ENTRY(MP_BC_CALL_FUNCTION): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800720 DECODE_UINT;
721 // unum & 0xff == n_positional
722 // (unum >> 8) & 0xff == n_keyword
723 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
724 SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
725 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000726 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800727
Damien Georgecd97a432014-12-02 19:25:10 +0000728 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800729 DECODE_UINT;
730 // unum & 0xff == n_positional
731 // (unum >> 8) & 0xff == n_keyword
732 // We have folowing stack layout here:
733 // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
734 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
735 SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
736 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000737 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800738
Damien Georgecd97a432014-12-02 19:25:10 +0000739 ENTRY(MP_BC_CALL_METHOD): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800740 DECODE_UINT;
741 // unum & 0xff == n_positional
742 // (unum >> 8) & 0xff == n_keyword
743 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
744 SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
745 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000746 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800747
Damien Georgecd97a432014-12-02 19:25:10 +0000748 ENTRY(MP_BC_CALL_METHOD_VAR_KW): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800749 DECODE_UINT;
750 // unum & 0xff == n_positional
751 // (unum >> 8) & 0xff == n_keyword
752 // We have folowing stack layout here:
753 // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
754 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
755 SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
756 DISPATCH();
Damien Georgecd97a432014-12-02 19:25:10 +0000757 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800758
759 ENTRY(MP_BC_RETURN_VALUE):
760unwind_return:
761 while (exc_sp >= exc_stack) {
762 if (exc_sp->opcode == MP_BC_SETUP_FINALLY || exc_sp->opcode == MP_BC_SETUP_WITH) {
763 // We're going to run "finally" code as a coroutine
764 // (not calling it recursively). Set up a sentinel
765 // on a stack so it can return back to us when it is
766 // done (when END_FINALLY reached).
767 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
768 ip = exc_sp->handler;
769 // We don't need to do anything with sp, finally is just
770 // syntactic sugar for sequential execution??
771 // sp =
772 exc_sp--;
773 goto dispatch_loop;
774 }
775 exc_sp--;
776 }
777 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300778 code_state->sp = sp;
AZ Huangb1f692e2014-04-14 23:22:44 +0800779 assert(exc_sp == exc_stack - 1);
780 return MP_VM_RETURN_NORMAL;
781
Damien Georged8675542014-05-25 22:58:04 +0100782 ENTRY(MP_BC_RAISE_VARARGS): {
Damien Georgecd97a432014-12-02 19:25:10 +0000783 mp_uint_t unum = *ip++;
Damien Georged8675542014-05-25 22:58:04 +0100784 mp_obj_t obj;
AZ Huangb1f692e2014-04-14 23:22:44 +0800785 assert(unum <= 1);
786 if (unum == 0) {
787 // search for the inner-most previous exception, to reraise it
Damien Georged8675542014-05-25 22:58:04 +0100788 obj = MP_OBJ_NULL;
AZ Huangb1f692e2014-04-14 23:22:44 +0800789 for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
790 if (e->prev_exc != MP_OBJ_NULL) {
Damien Georged8675542014-05-25 22:58:04 +0100791 obj = e->prev_exc;
AZ Huangb1f692e2014-04-14 23:22:44 +0800792 break;
793 }
794 }
Damien Georged8675542014-05-25 22:58:04 +0100795 if (obj == MP_OBJ_NULL) {
796 obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
797 RAISE(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +0800798 }
799 } else {
Damien Georged8675542014-05-25 22:58:04 +0100800 obj = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800801 }
Damien Georged8675542014-05-25 22:58:04 +0100802 obj = mp_make_raise_obj(obj);
803 RAISE(obj);
804 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800805
806 ENTRY(MP_BC_YIELD_VALUE):
807yield:
808 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300809 code_state->ip = ip;
810 code_state->sp = sp;
811 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +0800812 return MP_VM_RETURN_YIELD;
813
814 ENTRY(MP_BC_YIELD_FROM): {
815//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
816#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
Damien George66ae8c92014-04-17 16:50:23 +0100817#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 +0800818 mp_vm_return_kind_t ret_kind;
Damien Georged8675542014-05-25 22:58:04 +0100819 mp_obj_t send_value = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800820 mp_obj_t t_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100821 mp_obj_t ret_value;
AZ Huangb1f692e2014-04-14 23:22:44 +0800822 if (inject_exc != MP_OBJ_NULL) {
823 t_exc = inject_exc;
824 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100825 ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800826 } else {
Damien Georged8675542014-05-25 22:58:04 +0100827 ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800828 }
829
830 if (ret_kind == MP_VM_RETURN_YIELD) {
831 ip--;
Damien Georged8675542014-05-25 22:58:04 +0100832 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800833 goto yield;
834 }
835 if (ret_kind == MP_VM_RETURN_NORMAL) {
836 // Pop exhausted gen
837 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100838 if (ret_value == MP_OBJ_NULL) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800839 // Optimize StopIteration
840 // TODO: get StopIteration's value
841 PUSH(mp_const_none);
842 } else {
Damien Georged8675542014-05-25 22:58:04 +0100843 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800844 }
845
846 // If we injected GeneratorExit downstream, then even
847 // if it was swallowed, we re-raise GeneratorExit
848 GENERATOR_EXIT_IF_NEEDED(t_exc);
849 DISPATCH();
850 }
851 if (ret_kind == MP_VM_RETURN_EXCEPTION) {
852 // Pop exhausted gen
853 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100854 if (EXC_MATCH(ret_value, &mp_type_StopIteration)) {
855 PUSH(mp_obj_exception_get_value(ret_value));
AZ Huangb1f692e2014-04-14 23:22:44 +0800856 // If we injected GeneratorExit downstream, then even
857 // if it was swallowed, we re-raise GeneratorExit
858 GENERATOR_EXIT_IF_NEEDED(t_exc);
859 DISPATCH();
860 } else {
Damien Georged8675542014-05-25 22:58:04 +0100861 RAISE(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800862 }
863 }
Damien429d7192013-10-04 19:53:11 +0100864 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800865
Damien Georged8675542014-05-25 22:58:04 +0100866 ENTRY(MP_BC_IMPORT_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800867 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +0100868 mp_obj_t obj = POP();
869 SET_TOP(mp_import_name(qst, obj, TOP()));
AZ Huangb1f692e2014-04-14 23:22:44 +0800870 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100871 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800872
Damien Georged8675542014-05-25 22:58:04 +0100873 ENTRY(MP_BC_IMPORT_FROM): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800874 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +0100875 mp_obj_t obj = mp_import_from(TOP(), qst);
876 PUSH(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +0800877 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100878 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800879
880 ENTRY(MP_BC_IMPORT_STAR):
881 mp_import_all(POP());
882 DISPATCH();
883
Damien George8456cc02014-10-25 16:43:46 +0100884#if MICROPY_OPT_COMPUTED_GOTO
885 ENTRY(MP_BC_LOAD_CONST_SMALL_INT_MULTI):
886 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
887 DISPATCH();
888
889 ENTRY(MP_BC_LOAD_FAST_MULTI):
890 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
891 goto load_check;
892
893 ENTRY(MP_BC_STORE_FAST_MULTI):
894 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
895 DISPATCH();
896
897 ENTRY(MP_BC_UNARY_OP_MULTI):
898 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
899 DISPATCH();
900
901 ENTRY(MP_BC_BINARY_OP_MULTI): {
902 mp_obj_t rhs = POP();
903 mp_obj_t lhs = TOP();
904 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
905 DISPATCH();
906 }
907
908 ENTRY_DEFAULT:
909#else
910 ENTRY_DEFAULT:
911 if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
912 PUSH(MP_OBJ_NEW_SMALL_INT((mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16));
913 DISPATCH();
914 } else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
915 obj_shared = fastn[MP_BC_LOAD_FAST_MULTI - (mp_int_t)ip[-1]];
916 goto load_check;
917 } else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
918 fastn[MP_BC_STORE_FAST_MULTI - (mp_int_t)ip[-1]] = POP();
919 DISPATCH();
920 } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 5) {
921 SET_TOP(mp_unary_op(ip[-1] - MP_BC_UNARY_OP_MULTI, TOP()));
922 DISPATCH();
923 } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 35) {
924 mp_obj_t rhs = POP();
925 mp_obj_t lhs = TOP();
926 SET_TOP(mp_binary_op(ip[-1] - MP_BC_BINARY_OP_MULTI, lhs, rhs));
927 DISPATCH();
928 } else
929#endif
930 {
Damien Georged8675542014-05-25 22:58:04 +0100931 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
AZ Huangb1f692e2014-04-14 23:22:44 +0800932 nlr_pop();
Damien Georged8675542014-05-25 22:58:04 +0100933 fastn[0] = obj;
AZ Huangb1f692e2014-04-14 23:22:44 +0800934 return MP_VM_RETURN_EXCEPTION;
Damien Georged8675542014-05-25 22:58:04 +0100935 }
Damien George66ae8c92014-04-17 16:50:23 +0100936
Damien George58ebde42014-05-21 20:32:59 +0100937#if !MICROPY_OPT_COMPUTED_GOTO
AZ Huang9309d992014-04-15 15:57:01 +0800938 } // switch
AZ Huangb1f692e2014-04-14 23:22:44 +0800939#endif
Damien George124df6f2014-10-25 18:19:55 +0100940
941pending_exception_check:
942 if (mp_pending_exception != MP_OBJ_NULL) {
943 mp_obj_t obj = mp_pending_exception;
944 mp_pending_exception = MP_OBJ_NULL;
945 RAISE(obj);
946 }
Damien George124df6f2014-10-25 18:19:55 +0100947
Damien George66ae8c92014-04-17 16:50:23 +0100948 } // for loop
Damien429d7192013-10-04 19:53:11 +0100949
Damience89a212013-10-15 22:25:17 +0100950 } else {
Damien George66ae8c92014-04-17 16:50:23 +0100951exception_handler:
Damience89a212013-10-15 22:25:17 +0100952 // exception occurred
Damien429d7192013-10-04 19:53:11 +0100953
Damien George9e6e9352014-03-26 18:37:06 +0000954 // check if it's a StopIteration within a for block
Damien Georgec60a2612014-06-01 12:32:28 +0100955 if (*code_state->ip == MP_BC_FOR_ITER && mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) {
956 const byte *ip = code_state->ip + 1;
Damien George9e6e9352014-03-26 18:37:06 +0000957 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgecd97a432014-12-02 19:25:10 +0000958 code_state->ip = ip + ulab; // jump to after for-block
Damien Georgec60a2612014-06-01 12:32:28 +0100959 code_state->sp -= 1; // pop the exhausted iterator
Damien George9e6e9352014-03-26 18:37:06 +0000960 goto outer_dispatch_loop; // continue with dispatch loop
961 }
962
Damien George08335002014-01-18 23:24:36 +0000963 // set file and line number that the exception occurred at
Paul Sokolovsky382e8ee2014-01-30 13:49:18 +0200964 // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
965 // But consider how to handle nested exceptions.
Damien George6902eed2014-04-04 10:52:59 +0000966 // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
967 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 +0100968 const byte *ip = code_state->code_info;
969 mp_uint_t code_info_size = mp_decode_uint(&ip);
970 qstr block_name = mp_decode_uint(&ip);
971 qstr source_file = mp_decode_uint(&ip);
972 mp_uint_t bc = code_state->ip - code_state->code_info - code_info_size;
Damien Georgeb427d6a2014-08-26 23:35:57 +0100973 mp_uint_t source_line = 1;
974 mp_uint_t c;
Damien Georgeb534e1b2014-09-04 14:44:01 +0100975 while ((c = *ip)) {
Damien Georgeb427d6a2014-08-26 23:35:57 +0100976 mp_uint_t b, l;
977 if ((c & 0x80) == 0) {
978 // 0b0LLBBBBB encoding
979 b = c & 0x1f;
980 l = c >> 5;
Damien Georgeb534e1b2014-09-04 14:44:01 +0100981 ip += 1;
Damien Georgeb427d6a2014-08-26 23:35:57 +0100982 } else {
983 // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
984 b = c & 0xf;
Damien Georgeb534e1b2014-09-04 14:44:01 +0100985 l = ((c << 4) & 0x700) | ip[1];
986 ip += 2;
Damien Georgeb427d6a2014-08-26 23:35:57 +0100987 }
988 if (bc >= b) {
989 bc -= b;
990 source_line += l;
991 } else {
992 // found source line corresponding to bytecode offset
993 break;
Paul Sokolovsky411732e2014-06-02 18:24:34 +0300994 }
Damien George08335002014-01-18 23:24:36 +0000995 }
Damien George136b1492014-01-19 12:38:49 +0000996 mp_obj_exception_add_traceback(nlr.ret_val, source_file, source_line, block_name);
Damien George08335002014-01-18 23:24:36 +0000997 }
998
Damien8f9e2ee2013-12-29 16:54:59 +0000999 while (currently_in_except_block) {
1000 // nested exception
1001
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001002 assert(exc_sp >= exc_stack);
Damien8f9e2ee2013-12-29 16:54:59 +00001003
1004 // TODO make a proper message for nested exception
1005 // at the moment we are just raising the very last exception (the one that caused the nested exception)
1006
1007 // move up to previous exception handler
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +02001008 POP_EXC_BLOCK();
Damien8f9e2ee2013-12-29 16:54:59 +00001009 }
1010
Paul Sokolovskyc0abc282014-03-22 13:49:31 +02001011 if (exc_sp >= exc_stack) {
Damien8f9e2ee2013-12-29 16:54:59 +00001012 // set flag to indicate that we are now handling an exception
1013 currently_in_except_block = 1;
1014
Damience89a212013-10-15 22:25:17 +01001015 // catch exception and pass to byte code
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001016 code_state->ip = exc_sp->handler;
Damien George66ae8c92014-04-17 16:50:23 +01001017 mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
Damien Georged7592a12014-03-30 00:54:48 +00001018 // save this exception in the stack so it can be used in a reraise, if needed
1019 exc_sp->prev_exc = nlr.ret_val;
Damienc9f91972013-10-15 23:46:01 +01001020 // push(traceback, exc-val, exc-type)
Damiend99b0522013-12-21 18:17:45 +00001021 PUSH(mp_const_none);
Damienc9f91972013-10-15 23:46:01 +01001022 PUSH(nlr.ret_val);
Paul Sokolovsky682f9e62014-03-29 02:52:17 +02001023 PUSH(mp_obj_get_type(nlr.ret_val));
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +03001024 code_state->sp = sp;
Damien8f9e2ee2013-12-29 16:54:59 +00001025
Damience89a212013-10-15 22:25:17 +01001026 } else {
Damien Georgec8f78bc2014-02-15 22:55:00 +00001027 // propagate exception to higher level
1028 // TODO what to do about ip and sp? they don't really make sense at this point
1029 fastn[0] = nlr.ret_val; // must put exception here because sp is invalid
1030 return MP_VM_RETURN_EXCEPTION;
Damience89a212013-10-15 22:25:17 +01001031 }
Damien429d7192013-10-04 19:53:11 +01001032 }
1033 }
1034}