blob: d959880f122bedd63c73c463fd8d3ae803e8bd25 [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)
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
117 #define ENTRY(op) case op
118 #define ENTRY_DEFAULT default
AZ Huangb1f692e2014-04-14 23:22:44 +0800119#endif
120
Damien George66ae8c92014-04-17 16:50:23 +0100121 // nlr_raise needs to be implemented as a goto, so that the C compiler's flow analyser
122 // sees that it's possible for us to jump from the dispatch loop to the exception
123 // handler. Without this, the code may have a different stack layout in the dispatch
124 // loop and the exception handler, leading to very obscure bugs.
125 #define RAISE(o) do { nlr_pop(); nlr.ret_val = o; goto exception_handler; } while(0)
Damien429d7192013-10-04 19:53:11 +0100126
Damien Georgeaabd83e2014-06-07 14:16:08 +0100127 // Pointers which are constant for particular invocation of mp_execute_bytecode()
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300128 mp_obj_t *const fastn = &code_state->state[code_state->n_state - 1];
129 mp_exc_stack_t *const exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
130
Damien George66ae8c92014-04-17 16:50:23 +0100131 // variables that are visible to the exception handler (declared volatile)
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300132 volatile bool currently_in_except_block = MP_TAGPTR_TAG(code_state->exc_sp); // 0 or 1, to detect nested exceptions
133 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 +0100134
Damience89a212013-10-15 22:25:17 +0100135 // outer exception handling loop
Damien429d7192013-10-04 19:53:11 +0100136 for (;;) {
Damien George66ae8c92014-04-17 16:50:23 +0100137 nlr_buf_t nlr;
Damien George9e6e9352014-03-26 18:37:06 +0000138outer_dispatch_loop:
Damience89a212013-10-15 22:25:17 +0100139 if (nlr_push(&nlr) == 0) {
Damien George66ae8c92014-04-17 16:50:23 +0100140 // local variables that are not visible to the exception handler
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300141 const byte *ip = code_state->ip;
142 mp_obj_t *sp = code_state->sp;
Damien George40f3c022014-07-03 13:25:24 +0100143 mp_uint_t unum;
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
AZ Huangb1f692e2014-04-14 23:22:44 +0800226 ENTRY(MP_BC_LOAD_FAST_0):
Damien Georged8675542014-05-25 22:58:04 +0100227 obj_shared = fastn[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800228 goto load_check;
Damience89a212013-10-15 22:25:17 +0100229
AZ Huangb1f692e2014-04-14 23:22:44 +0800230 ENTRY(MP_BC_LOAD_FAST_1):
Damien Georged8675542014-05-25 22:58:04 +0100231 obj_shared = fastn[-1];
AZ Huangb1f692e2014-04-14 23:22:44 +0800232 goto load_check;
Damience89a212013-10-15 22:25:17 +0100233
AZ Huangb1f692e2014-04-14 23:22:44 +0800234 ENTRY(MP_BC_LOAD_FAST_2):
Damien Georged8675542014-05-25 22:58:04 +0100235 obj_shared = fastn[-2];
AZ Huangb1f692e2014-04-14 23:22:44 +0800236 goto load_check;
Damience89a212013-10-15 22:25:17 +0100237
AZ Huangb1f692e2014-04-14 23:22:44 +0800238 ENTRY(MP_BC_LOAD_FAST_N):
239 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100240 obj_shared = fastn[-unum];
AZ Huangb1f692e2014-04-14 23:22:44 +0800241 load_check:
Damien Georged8675542014-05-25 22:58:04 +0100242 if (obj_shared == MP_OBJ_NULL) {
243 local_name_error: {
244 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment");
245 RAISE(obj);
246 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800247 }
Damien Georged8675542014-05-25 22:58:04 +0100248 PUSH(obj_shared);
AZ Huangb1f692e2014-04-14 23:22:44 +0800249 DISPATCH();
Damien George2bf7c092014-04-09 15:26:46 +0100250
AZ Huangb1f692e2014-04-14 23:22:44 +0800251 ENTRY(MP_BC_LOAD_DEREF):
252 DECODE_UINT;
Damien Georged8675542014-05-25 22:58:04 +0100253 obj_shared = mp_obj_cell_get(fastn[-unum]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800254 goto load_check;
Damien9ecbcff2013-12-11 00:41:43 +0000255
Damien Georged8675542014-05-25 22:58:04 +0100256 ENTRY(MP_BC_LOAD_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800257 DECODE_QSTR;
258 PUSH(mp_load_name(qst));
259 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100260 }
Damience89a212013-10-15 22:25:17 +0100261
Damien Georged8675542014-05-25 22:58:04 +0100262 ENTRY(MP_BC_LOAD_GLOBAL): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800263 DECODE_QSTR;
264 PUSH(mp_load_global(qst));
265 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100266 }
Damience89a212013-10-15 22:25:17 +0100267
Damien Georged8675542014-05-25 22:58:04 +0100268 ENTRY(MP_BC_LOAD_ATTR): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800269 DECODE_QSTR;
270 SET_TOP(mp_load_attr(TOP(), qst));
271 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100272 }
Damience89a212013-10-15 22:25:17 +0100273
Damien Georged8675542014-05-25 22:58:04 +0100274 ENTRY(MP_BC_LOAD_METHOD): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800275 DECODE_QSTR;
276 mp_load_method(*sp, qst, sp);
277 sp += 1;
278 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100279 }
Damience89a212013-10-15 22:25:17 +0100280
AZ Huangb1f692e2014-04-14 23:22:44 +0800281 ENTRY(MP_BC_LOAD_BUILD_CLASS):
282 PUSH(mp_load_build_class());
283 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100284
Damien Georged8675542014-05-25 22:58:04 +0100285 ENTRY(MP_BC_LOAD_SUBSCR): {
286 mp_obj_t index = POP();
287 SET_TOP(mp_obj_subscr(TOP(), index, MP_OBJ_SENTINEL));
Damien George729f7b42014-04-17 22:10:53 +0100288 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100289 }
Damien George729f7b42014-04-17 22:10:53 +0100290
AZ Huangb1f692e2014-04-14 23:22:44 +0800291 ENTRY(MP_BC_STORE_FAST_0):
292 fastn[0] = POP();
293 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100294
AZ Huangb1f692e2014-04-14 23:22:44 +0800295 ENTRY(MP_BC_STORE_FAST_1):
296 fastn[-1] = POP();
297 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100298
AZ Huangb1f692e2014-04-14 23:22:44 +0800299 ENTRY(MP_BC_STORE_FAST_2):
300 fastn[-2] = POP();
301 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100302
AZ Huangb1f692e2014-04-14 23:22:44 +0800303 ENTRY(MP_BC_STORE_FAST_N):
304 DECODE_UINT;
305 fastn[-unum] = POP();
306 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100307
AZ Huangb1f692e2014-04-14 23:22:44 +0800308 ENTRY(MP_BC_STORE_DEREF):
309 DECODE_UINT;
310 mp_obj_cell_set(fastn[-unum], POP());
311 DISPATCH();
Damien9ecbcff2013-12-11 00:41:43 +0000312
Damien Georged8675542014-05-25 22:58:04 +0100313 ENTRY(MP_BC_STORE_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800314 DECODE_QSTR;
315 mp_store_name(qst, POP());
316 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100317 }
Damience89a212013-10-15 22:25:17 +0100318
Damien Georged8675542014-05-25 22:58:04 +0100319 ENTRY(MP_BC_STORE_GLOBAL): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800320 DECODE_QSTR;
321 mp_store_global(qst, POP());
322 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100323 }
Damien6addc892013-11-04 23:04:50 +0000324
Damien Georged8675542014-05-25 22:58:04 +0100325 ENTRY(MP_BC_STORE_ATTR): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800326 DECODE_QSTR;
327 mp_store_attr(sp[0], qst, sp[-1]);
328 sp -= 2;
329 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100330 }
Damience89a212013-10-15 22:25:17 +0100331
AZ Huangb1f692e2014-04-14 23:22:44 +0800332 ENTRY(MP_BC_STORE_SUBSCR):
Damien George729f7b42014-04-17 22:10:53 +0100333 mp_obj_subscr(sp[-1], sp[0], sp[-2]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800334 sp -= 3;
335 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100336
AZ Huangb1f692e2014-04-14 23:22:44 +0800337 ENTRY(MP_BC_DELETE_FAST):
338 DECODE_UINT;
339 if (fastn[-unum] == MP_OBJ_NULL) {
340 goto local_name_error;
341 }
342 fastn[-unum] = MP_OBJ_NULL;
343 DISPATCH();
Damien George2bf7c092014-04-09 15:26:46 +0100344
AZ Huangb1f692e2014-04-14 23:22:44 +0800345 ENTRY(MP_BC_DELETE_DEREF):
346 DECODE_UINT;
347 if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
348 goto local_name_error;
349 }
350 mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);
351 DISPATCH();
Damien George2bf7c092014-04-09 15:26:46 +0100352
Damien Georged8675542014-05-25 22:58:04 +0100353 ENTRY(MP_BC_DELETE_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800354 DECODE_QSTR;
355 mp_delete_name(qst);
356 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100357 }
Paul Sokolovskyf9090342014-03-23 21:19:02 +0200358
Damien Georged8675542014-05-25 22:58:04 +0100359 ENTRY(MP_BC_DELETE_GLOBAL): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800360 DECODE_QSTR;
361 mp_delete_global(qst);
362 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100363 }
Damien George1d24ea52014-04-08 21:11:49 +0100364
Damien Georged8675542014-05-25 22:58:04 +0100365 ENTRY(MP_BC_DUP_TOP): {
366 mp_obj_t top = TOP();
367 PUSH(top);
AZ Huangb1f692e2014-04-14 23:22:44 +0800368 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100369 }
Damience89a212013-10-15 22:25:17 +0100370
AZ Huangb1f692e2014-04-14 23:22:44 +0800371 ENTRY(MP_BC_DUP_TOP_TWO):
372 sp += 2;
373 sp[0] = sp[-2];
374 sp[-1] = sp[-3];
375 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100376
AZ Huangb1f692e2014-04-14 23:22:44 +0800377 ENTRY(MP_BC_POP_TOP):
378 sp -= 1;
379 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100380
Damien Georged8675542014-05-25 22:58:04 +0100381 ENTRY(MP_BC_ROT_TWO): {
382 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800383 sp[0] = sp[-1];
Damien Georged8675542014-05-25 22:58:04 +0100384 sp[-1] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800385 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100386 }
Damien4ebb32f2013-11-02 14:33:10 +0000387
Damien Georged8675542014-05-25 22:58:04 +0100388 ENTRY(MP_BC_ROT_THREE): {
389 mp_obj_t top = sp[0];
AZ Huangb1f692e2014-04-14 23:22:44 +0800390 sp[0] = sp[-1];
391 sp[-1] = sp[-2];
Damien Georged8675542014-05-25 22:58:04 +0100392 sp[-2] = top;
AZ Huangb1f692e2014-04-14 23:22:44 +0800393 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100394 }
Damience89a212013-10-15 22:25:17 +0100395
AZ Huangb1f692e2014-04-14 23:22:44 +0800396 ENTRY(MP_BC_JUMP):
397 DECODE_SLABEL;
398 ip += unum;
399 DISPATCH();
400
401 ENTRY(MP_BC_POP_JUMP_IF_TRUE):
402 DECODE_SLABEL;
403 if (mp_obj_is_true(POP())) {
Damien03c9cfb2013-11-05 22:06:08 +0000404 ip += unum;
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200405 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800406 DISPATCH();
Paul Sokolovsky44307d52014-03-29 04:10:11 +0200407
AZ Huangb1f692e2014-04-14 23:22:44 +0800408 ENTRY(MP_BC_POP_JUMP_IF_FALSE):
409 DECODE_SLABEL;
410 if (!mp_obj_is_true(POP())) {
411 ip += unum;
412 }
413 DISPATCH();
Damien George600ae732014-01-21 23:48:04 +0000414
AZ Huangb1f692e2014-04-14 23:22:44 +0800415 ENTRY(MP_BC_JUMP_IF_TRUE_OR_POP):
416 DECODE_SLABEL;
417 if (mp_obj_is_true(TOP())) {
418 ip += unum;
419 } else {
420 sp--;
421 }
422 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100423
AZ Huangb1f692e2014-04-14 23:22:44 +0800424 ENTRY(MP_BC_JUMP_IF_FALSE_OR_POP):
425 DECODE_SLABEL;
426 if (mp_obj_is_true(TOP())) {
427 sp--;
428 } else {
429 ip += unum;
430 }
431 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100432
Damien Georged8675542014-05-25 22:58:04 +0100433 ENTRY(MP_BC_SETUP_WITH): {
434 mp_obj_t obj = TOP();
435 SET_TOP(mp_load_attr(obj, MP_QSTR___exit__));
436 mp_load_method(obj, MP_QSTR___enter__, sp + 1);
437 mp_obj_t ret = mp_call_method_n_kw(0, 0, sp + 1);
AZ Huangb1f692e2014-04-14 23:22:44 +0800438 PUSH_EXC_BLOCK();
Damien Georged8675542014-05-25 22:58:04 +0100439 PUSH(ret);
AZ Huangb1f692e2014-04-14 23:22:44 +0800440 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100441 }
Damience89a212013-10-15 22:25:17 +0100442
AZ Huangb1f692e2014-04-14 23:22:44 +0800443 ENTRY(MP_BC_WITH_CLEANUP): {
444 // Arriving here, there's "exception control block" on top of stack,
445 // and __exit__ bound method underneath it. Bytecode calls __exit__,
446 // and "deletes" it off stack, shifting "exception control block"
447 // to its place.
448 static const mp_obj_t no_exc[] = {mp_const_none, mp_const_none, mp_const_none};
449 if (TOP() == mp_const_none) {
450 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100451 mp_obj_t obj = TOP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800452 SET_TOP(mp_const_none);
Damien Georged8675542014-05-25 22:58:04 +0100453 mp_call_function_n_kw(obj, 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800454 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
455 mp_obj_t cause = POP();
456 switch (MP_OBJ_SMALL_INT_VALUE(cause)) {
457 case UNWIND_RETURN: {
458 mp_obj_t retval = POP();
Damien Georged8675542014-05-25 22:58:04 +0100459 mp_call_function_n_kw(TOP(), 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800460 SET_TOP(retval);
461 PUSH(cause);
462 break;
463 }
464 case UNWIND_JUMP: {
Damien Georged8675542014-05-25 22:58:04 +0100465 mp_call_function_n_kw(sp[-2], 3, 0, no_exc);
AZ Huangb1f692e2014-04-14 23:22:44 +0800466 // Pop __exit__ boundmethod at sp[-2]
467 sp[-2] = sp[-1];
468 sp[-1] = sp[0];
469 SET_TOP(cause);
470 break;
471 }
472 default:
473 assert(0);
474 }
475 } else if (mp_obj_is_exception_type(TOP())) {
476 mp_obj_t args[3] = {sp[0], sp[-1], sp[-2]};
Damien Georged8675542014-05-25 22:58:04 +0100477 mp_obj_t ret_value = mp_call_function_n_kw(sp[-3], 3, 0, args);
AZ Huangb1f692e2014-04-14 23:22:44 +0800478 // Pop __exit__ boundmethod at sp[-3]
Damien Georged8675542014-05-25 22:58:04 +0100479 // TODO: Once semantics is proven, optimize for case when ret_value == True
AZ Huangb1f692e2014-04-14 23:22:44 +0800480 sp[-3] = sp[-2];
481 sp[-2] = sp[-1];
482 sp[-1] = sp[0];
Damien George20006db2014-01-18 14:10:48 +0000483 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100484 if (mp_obj_is_true(ret_value)) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800485 // This is what CPython does
486 //PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_SILENCED));
487 // But what we need to do is - pop exception from value stack...
488 sp -= 3;
489 // ... pop "with" exception handler, and signal END_FINALLY
490 // to just execute finally handler normally (by pushing None
491 // on value stack)
492 assert(exc_sp >= exc_stack);
493 assert(exc_sp->opcode == MP_BC_SETUP_WITH);
494 POP_EXC_BLOCK();
495 PUSH(mp_const_none);
496 }
497 } else {
498 assert(0);
499 }
500 DISPATCH();
501 }
Damienc226dca2013-10-16 16:12:52 +0100502
AZ Huangb1f692e2014-04-14 23:22:44 +0800503 ENTRY(MP_BC_UNWIND_JUMP):
504 DECODE_SLABEL;
505 PUSH((void*)(ip + unum)); // push destination ip for jump
Damien George40f3c022014-07-03 13:25:24 +0100506 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 +0800507unwind_jump:
Damien George40f3c022014-07-03 13:25:24 +0100508 unum = (mp_uint_t)POP(); // get number of exception handlers to unwind
Damien George25c84642014-05-30 15:20:41 +0100509 while ((unum & 0x7f) > 0) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800510 unum -= 1;
511 assert(exc_sp >= exc_stack);
512 if (exc_sp->opcode == MP_BC_SETUP_FINALLY || exc_sp->opcode == MP_BC_SETUP_WITH) {
513 // We're going to run "finally" code as a coroutine
514 // (not calling it recursively). Set up a sentinel
515 // on a stack so it can return back to us when it is
516 // done (when END_FINALLY reached).
517 PUSH((void*)unum); // push number of exception handlers left to unwind
518 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
519 ip = exc_sp->handler; // get exception handler byte code address
520 exc_sp--; // pop exception handler
521 goto dispatch_loop; // run the exception handler
522 }
523 exc_sp--;
524 }
525 ip = (const byte*)POP(); // pop destination ip for jump
Damien George25c84642014-05-30 15:20:41 +0100526 if (unum != 0) {
527 sp--;
528 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800529 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100530
AZ Huangb1f692e2014-04-14 23:22:44 +0800531 // matched against: POP_BLOCK or POP_EXCEPT (anything else?)
532 ENTRY(MP_BC_SETUP_EXCEPT):
533 ENTRY(MP_BC_SETUP_FINALLY):
534 PUSH_EXC_BLOCK();
535 DISPATCH();
Damience89a212013-10-15 22:25:17 +0100536
AZ Huangb1f692e2014-04-14 23:22:44 +0800537 ENTRY(MP_BC_END_FINALLY):
538 // not fully implemented
539 // if TOS is an exception, reraises the exception (3 values on TOS)
540 // if TOS is None, just pops it and continues
541 // if TOS is an integer, does something else
542 // else error
543 if (mp_obj_is_exception_type(TOP())) {
Damien George66ae8c92014-04-17 16:50:23 +0100544 RAISE(sp[-1]);
AZ Huangb1f692e2014-04-14 23:22:44 +0800545 }
546 if (TOP() == mp_const_none) {
Damien George20006db2014-01-18 14:10:48 +0000547 sp--;
AZ Huangb1f692e2014-04-14 23:22:44 +0800548 } else if (MP_OBJ_IS_SMALL_INT(TOP())) {
549 // We finished "finally" coroutine and now dispatch back
550 // to our caller, based on TOS value
551 mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());
552 switch (reason) {
553 case UNWIND_RETURN:
554 goto unwind_return;
555 case UNWIND_JUMP:
556 goto unwind_jump;
557 }
558 assert(0);
559 } else {
560 assert(0);
561 }
562 DISPATCH();
563
564 ENTRY(MP_BC_GET_ITER):
565 SET_TOP(mp_getiter(TOP()));
566 DISPATCH();
567
Damien Georged8675542014-05-25 22:58:04 +0100568 ENTRY(MP_BC_FOR_ITER): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800569 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damien Georgec60a2612014-06-01 12:32:28 +0100570 code_state->sp = sp;
Paul Sokolovskyc48d6f72014-05-11 20:32:39 +0300571 assert(TOP());
Damien Georged8675542014-05-25 22:58:04 +0100572 mp_obj_t value = mp_iternext_allow_raise(TOP());
573 if (value == MP_OBJ_STOP_ITERATION) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800574 --sp; // pop the exhausted iterator
575 ip += unum; // jump to after for-block
576 } else {
Damien Georged8675542014-05-25 22:58:04 +0100577 PUSH(value); // push the next iteration value
AZ Huangb1f692e2014-04-14 23:22:44 +0800578 }
579 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100580 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800581
582 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
583 ENTRY(MP_BC_POP_BLOCK):
584 // we are exiting an exception handler, so pop the last one of the exception-stack
585 assert(exc_sp >= exc_stack);
586 POP_EXC_BLOCK();
587 DISPATCH();
588
589 // matched against: SETUP_EXCEPT
590 ENTRY(MP_BC_POP_EXCEPT):
591 // TODO need to work out how blocks work etc
592 // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
593 assert(exc_sp >= exc_stack);
594 assert(currently_in_except_block);
595 //sp = (mp_obj_t*)(*exc_sp--);
596 //exc_sp--; // discard ip
597 POP_EXC_BLOCK();
598 //sp -= 3; // pop 3 exception values
599 DISPATCH();
600
601 ENTRY(MP_BC_NOT):
602 if (TOP() == mp_const_true) {
603 SET_TOP(mp_const_false);
604 } else {
605 SET_TOP(mp_const_true);
606 }
607 DISPATCH();
608
609 ENTRY(MP_BC_UNARY_OP):
610 unum = *ip++;
611 SET_TOP(mp_unary_op(unum, TOP()));
612 DISPATCH();
613
Damien Georged8675542014-05-25 22:58:04 +0100614 ENTRY(MP_BC_BINARY_OP): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800615 unum = *ip++;
Damien Georged8675542014-05-25 22:58:04 +0100616 mp_obj_t rhs = POP();
617 mp_obj_t lhs = TOP();
618 SET_TOP(mp_binary_op(unum, lhs, rhs));
AZ Huangb1f692e2014-04-14 23:22:44 +0800619 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100620 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800621
622 ENTRY(MP_BC_BUILD_TUPLE):
623 DECODE_UINT;
624 sp -= unum - 1;
625 SET_TOP(mp_obj_new_tuple(unum, sp));
626 DISPATCH();
627
628 ENTRY(MP_BC_BUILD_LIST):
629 DECODE_UINT;
630 sp -= unum - 1;
631 SET_TOP(mp_obj_new_list(unum, sp));
632 DISPATCH();
633
634 ENTRY(MP_BC_LIST_APPEND):
635 DECODE_UINT;
636 // I think it's guaranteed by the compiler that sp[unum] is a list
637 mp_obj_list_append(sp[-unum], sp[0]);
638 sp--;
639 DISPATCH();
640
641 ENTRY(MP_BC_BUILD_MAP):
642 DECODE_UINT;
643 PUSH(mp_obj_new_dict(unum));
644 DISPATCH();
645
646 ENTRY(MP_BC_STORE_MAP):
647 sp -= 2;
648 mp_obj_dict_store(sp[0], sp[2], sp[1]);
649 DISPATCH();
650
651 ENTRY(MP_BC_MAP_ADD):
652 DECODE_UINT;
653 // I think it's guaranteed by the compiler that sp[-unum - 1] is a map
654 mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]);
655 sp -= 2;
656 DISPATCH();
657
Damien George3ebd4d02014-06-01 13:46:47 +0100658#if MICROPY_PY_BUILTINS_SET
AZ Huangb1f692e2014-04-14 23:22:44 +0800659 ENTRY(MP_BC_BUILD_SET):
660 DECODE_UINT;
661 sp -= unum - 1;
662 SET_TOP(mp_obj_new_set(unum, sp));
663 DISPATCH();
664
665 ENTRY(MP_BC_SET_ADD):
666 DECODE_UINT;
667 // I think it's guaranteed by the compiler that sp[-unum] is a set
668 mp_obj_set_store(sp[-unum], sp[0]);
669 sp--;
670 DISPATCH();
Damien George3ebd4d02014-06-01 13:46:47 +0100671#endif
Damienc12aa462013-10-16 20:57:49 +0100672
Damien Georgefb510b32014-06-01 13:32:54 +0100673#if MICROPY_PY_BUILTINS_SLICE
AZ Huangb1f692e2014-04-14 23:22:44 +0800674 ENTRY(MP_BC_BUILD_SLICE):
675 DECODE_UINT;
676 if (unum == 2) {
Damien Georged8675542014-05-25 22:58:04 +0100677 mp_obj_t stop = POP();
678 mp_obj_t start = TOP();
679 SET_TOP(mp_obj_new_slice(start, stop, mp_const_none));
AZ Huangb1f692e2014-04-14 23:22:44 +0800680 } else {
Damien Georged8675542014-05-25 22:58:04 +0100681 mp_obj_t step = POP();
682 mp_obj_t stop = POP();
683 mp_obj_t start = TOP();
684 SET_TOP(mp_obj_new_slice(start, stop, step));
AZ Huangb1f692e2014-04-14 23:22:44 +0800685 }
686 DISPATCH();
687#endif
688
689 ENTRY(MP_BC_UNPACK_SEQUENCE):
690 DECODE_UINT;
691 mp_unpack_sequence(sp[0], unum, sp);
692 sp += unum - 1;
693 DISPATCH();
694
695 ENTRY(MP_BC_UNPACK_EX):
696 DECODE_UINT;
697 mp_unpack_ex(sp[0], unum, sp);
698 sp += (unum & 0xff) + ((unum >> 8) & 0xff);
699 DISPATCH();
700
701 ENTRY(MP_BC_MAKE_FUNCTION):
702 DECODE_PTR;
703 PUSH(mp_make_function_from_raw_code((mp_raw_code_t*)unum, MP_OBJ_NULL, MP_OBJ_NULL));
704 DISPATCH();
705
Damien Georged8675542014-05-25 22:58:04 +0100706 ENTRY(MP_BC_MAKE_FUNCTION_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800707 DECODE_PTR;
708 // Stack layout: def_tuple def_dict <- TOS
Damien Georged8675542014-05-25 22:58:04 +0100709 mp_obj_t def_dict = POP();
710 SET_TOP(mp_make_function_from_raw_code((mp_raw_code_t*)unum, TOP(), def_dict));
AZ Huangb1f692e2014-04-14 23:22:44 +0800711 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100712 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800713
Damien George3558f622014-04-20 17:50:40 +0100714 ENTRY(MP_BC_MAKE_CLOSURE): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800715 DECODE_PTR;
Damien George40f3c022014-07-03 13:25:24 +0100716 mp_uint_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100717 // Stack layout: closed_overs <- TOS
718 sp -= n_closed_over - 1;
719 SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, n_closed_over, sp));
AZ Huangb1f692e2014-04-14 23:22:44 +0800720 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100721 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800722
Damien George3558f622014-04-20 17:50:40 +0100723 ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800724 DECODE_PTR;
Damien George40f3c022014-07-03 13:25:24 +0100725 mp_uint_t n_closed_over = *ip++;
Damien George3558f622014-04-20 17:50:40 +0100726 // Stack layout: def_tuple def_dict closed_overs <- TOS
727 sp -= 2 + n_closed_over - 1;
728 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 +0800729 DISPATCH();
Damien George3558f622014-04-20 17:50:40 +0100730 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800731
732 ENTRY(MP_BC_CALL_FUNCTION):
733 DECODE_UINT;
734 // unum & 0xff == n_positional
735 // (unum >> 8) & 0xff == n_keyword
736 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
737 SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
738 DISPATCH();
739
740 ENTRY(MP_BC_CALL_FUNCTION_VAR_KW):
741 DECODE_UINT;
742 // unum & 0xff == n_positional
743 // (unum >> 8) & 0xff == n_keyword
744 // We have folowing stack layout here:
745 // fun arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
746 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 2;
747 SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
748 DISPATCH();
749
750 ENTRY(MP_BC_CALL_METHOD):
751 DECODE_UINT;
752 // unum & 0xff == n_positional
753 // (unum >> 8) & 0xff == n_keyword
754 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
755 SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
756 DISPATCH();
757
758 ENTRY(MP_BC_CALL_METHOD_VAR_KW):
759 DECODE_UINT;
760 // unum & 0xff == n_positional
761 // (unum >> 8) & 0xff == n_keyword
762 // We have folowing stack layout here:
763 // fun self arg0 arg1 ... kw0 val0 kw1 val1 ... seq dict <- TOS
764 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 3;
765 SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
766 DISPATCH();
767
768 ENTRY(MP_BC_RETURN_VALUE):
769unwind_return:
770 while (exc_sp >= exc_stack) {
771 if (exc_sp->opcode == MP_BC_SETUP_FINALLY || exc_sp->opcode == MP_BC_SETUP_WITH) {
772 // We're going to run "finally" code as a coroutine
773 // (not calling it recursively). Set up a sentinel
774 // on a stack so it can return back to us when it is
775 // done (when END_FINALLY reached).
776 PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
777 ip = exc_sp->handler;
778 // We don't need to do anything with sp, finally is just
779 // syntactic sugar for sequential execution??
780 // sp =
781 exc_sp--;
782 goto dispatch_loop;
783 }
784 exc_sp--;
785 }
786 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300787 code_state->sp = sp;
AZ Huangb1f692e2014-04-14 23:22:44 +0800788 assert(exc_sp == exc_stack - 1);
789 return MP_VM_RETURN_NORMAL;
790
Damien Georged8675542014-05-25 22:58:04 +0100791 ENTRY(MP_BC_RAISE_VARARGS): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800792 unum = *ip++;
Damien Georged8675542014-05-25 22:58:04 +0100793 mp_obj_t obj;
AZ Huangb1f692e2014-04-14 23:22:44 +0800794 assert(unum <= 1);
795 if (unum == 0) {
796 // search for the inner-most previous exception, to reraise it
Damien Georged8675542014-05-25 22:58:04 +0100797 obj = MP_OBJ_NULL;
AZ Huangb1f692e2014-04-14 23:22:44 +0800798 for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
799 if (e->prev_exc != MP_OBJ_NULL) {
Damien Georged8675542014-05-25 22:58:04 +0100800 obj = e->prev_exc;
AZ Huangb1f692e2014-04-14 23:22:44 +0800801 break;
802 }
803 }
Damien Georged8675542014-05-25 22:58:04 +0100804 if (obj == MP_OBJ_NULL) {
805 obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
806 RAISE(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +0800807 }
808 } else {
Damien Georged8675542014-05-25 22:58:04 +0100809 obj = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800810 }
Damien Georged8675542014-05-25 22:58:04 +0100811 obj = mp_make_raise_obj(obj);
812 RAISE(obj);
813 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800814
815 ENTRY(MP_BC_YIELD_VALUE):
816yield:
817 nlr_pop();
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300818 code_state->ip = ip;
819 code_state->sp = sp;
820 code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
AZ Huangb1f692e2014-04-14 23:22:44 +0800821 return MP_VM_RETURN_YIELD;
822
823 ENTRY(MP_BC_YIELD_FROM): {
824//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
825#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
Damien George66ae8c92014-04-17 16:50:23 +0100826#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 +0800827 mp_vm_return_kind_t ret_kind;
Damien Georged8675542014-05-25 22:58:04 +0100828 mp_obj_t send_value = POP();
AZ Huangb1f692e2014-04-14 23:22:44 +0800829 mp_obj_t t_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100830 mp_obj_t ret_value;
AZ Huangb1f692e2014-04-14 23:22:44 +0800831 if (inject_exc != MP_OBJ_NULL) {
832 t_exc = inject_exc;
833 inject_exc = MP_OBJ_NULL;
Damien Georged8675542014-05-25 22:58:04 +0100834 ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800835 } else {
Damien Georged8675542014-05-25 22:58:04 +0100836 ret_kind = mp_resume(TOP(), send_value, MP_OBJ_NULL, &ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800837 }
838
839 if (ret_kind == MP_VM_RETURN_YIELD) {
840 ip--;
Damien Georged8675542014-05-25 22:58:04 +0100841 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800842 goto yield;
843 }
844 if (ret_kind == MP_VM_RETURN_NORMAL) {
845 // Pop exhausted gen
846 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100847 if (ret_value == MP_OBJ_NULL) {
AZ Huangb1f692e2014-04-14 23:22:44 +0800848 // Optimize StopIteration
849 // TODO: get StopIteration's value
850 PUSH(mp_const_none);
851 } else {
Damien Georged8675542014-05-25 22:58:04 +0100852 PUSH(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800853 }
854
855 // If we injected GeneratorExit downstream, then even
856 // if it was swallowed, we re-raise GeneratorExit
857 GENERATOR_EXIT_IF_NEEDED(t_exc);
858 DISPATCH();
859 }
860 if (ret_kind == MP_VM_RETURN_EXCEPTION) {
861 // Pop exhausted gen
862 sp--;
Damien Georged8675542014-05-25 22:58:04 +0100863 if (EXC_MATCH(ret_value, &mp_type_StopIteration)) {
864 PUSH(mp_obj_exception_get_value(ret_value));
AZ Huangb1f692e2014-04-14 23:22:44 +0800865 // If we injected GeneratorExit downstream, then even
866 // if it was swallowed, we re-raise GeneratorExit
867 GENERATOR_EXIT_IF_NEEDED(t_exc);
868 DISPATCH();
869 } else {
Damien Georged8675542014-05-25 22:58:04 +0100870 RAISE(ret_value);
AZ Huangb1f692e2014-04-14 23:22:44 +0800871 }
872 }
Damien429d7192013-10-04 19:53:11 +0100873 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800874
Damien Georged8675542014-05-25 22:58:04 +0100875 ENTRY(MP_BC_IMPORT_NAME): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800876 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +0100877 mp_obj_t obj = POP();
878 SET_TOP(mp_import_name(qst, obj, TOP()));
AZ Huangb1f692e2014-04-14 23:22:44 +0800879 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100880 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800881
Damien Georged8675542014-05-25 22:58:04 +0100882 ENTRY(MP_BC_IMPORT_FROM): {
AZ Huangb1f692e2014-04-14 23:22:44 +0800883 DECODE_QSTR;
Damien Georged8675542014-05-25 22:58:04 +0100884 mp_obj_t obj = mp_import_from(TOP(), qst);
885 PUSH(obj);
AZ Huangb1f692e2014-04-14 23:22:44 +0800886 DISPATCH();
Damien Georged8675542014-05-25 22:58:04 +0100887 }
AZ Huangb1f692e2014-04-14 23:22:44 +0800888
889 ENTRY(MP_BC_IMPORT_STAR):
890 mp_import_all(POP());
891 DISPATCH();
892
Damien Georged8675542014-05-25 22:58:04 +0100893 ENTRY_DEFAULT: {
894 mp_obj_t obj = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
AZ Huangb1f692e2014-04-14 23:22:44 +0800895 nlr_pop();
Damien Georged8675542014-05-25 22:58:04 +0100896 fastn[0] = obj;
AZ Huangb1f692e2014-04-14 23:22:44 +0800897 return MP_VM_RETURN_EXCEPTION;
Damien Georged8675542014-05-25 22:58:04 +0100898 }
Damien George66ae8c92014-04-17 16:50:23 +0100899
Damien George58ebde42014-05-21 20:32:59 +0100900#if !MICROPY_OPT_COMPUTED_GOTO
AZ Huang9309d992014-04-15 15:57:01 +0800901 } // switch
AZ Huangb1f692e2014-04-14 23:22:44 +0800902#endif
Damien George66ae8c92014-04-17 16:50:23 +0100903 } // for loop
Damien429d7192013-10-04 19:53:11 +0100904
Damience89a212013-10-15 22:25:17 +0100905 } else {
Damien George66ae8c92014-04-17 16:50:23 +0100906exception_handler:
Damience89a212013-10-15 22:25:17 +0100907 // exception occurred
Damien429d7192013-10-04 19:53:11 +0100908
Damien George9e6e9352014-03-26 18:37:06 +0000909 // check if it's a StopIteration within a for block
Damien Georgec60a2612014-06-01 12:32:28 +0100910 if (*code_state->ip == MP_BC_FOR_ITER && mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) {
911 const byte *ip = code_state->ip + 1;
Damien George40f3c022014-07-03 13:25:24 +0100912 mp_uint_t unum;
Damien George9e6e9352014-03-26 18:37:06 +0000913 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300914 code_state->ip = ip + unum; // jump to after for-block
Damien Georgec60a2612014-06-01 12:32:28 +0100915 code_state->sp -= 1; // pop the exhausted iterator
Damien George9e6e9352014-03-26 18:37:06 +0000916 goto outer_dispatch_loop; // continue with dispatch loop
917 }
918
Damien George08335002014-01-18 23:24:36 +0000919 // set file and line number that the exception occurred at
Paul Sokolovsky382e8ee2014-01-30 13:49:18 +0200920 // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
921 // But consider how to handle nested exceptions.
Damien George6902eed2014-04-04 10:52:59 +0000922 // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
923 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 +0100924 const byte *ip = code_state->code_info;
925 mp_uint_t code_info_size = mp_decode_uint(&ip);
926 qstr block_name = mp_decode_uint(&ip);
927 qstr source_file = mp_decode_uint(&ip);
928 mp_uint_t bc = code_state->ip - code_state->code_info - code_info_size;
Damien Georgeb427d6a2014-08-26 23:35:57 +0100929 mp_uint_t source_line = 1;
930 mp_uint_t c;
Damien Georgeb534e1b2014-09-04 14:44:01 +0100931 while ((c = *ip)) {
Damien Georgeb427d6a2014-08-26 23:35:57 +0100932 mp_uint_t b, l;
933 if ((c & 0x80) == 0) {
934 // 0b0LLBBBBB encoding
935 b = c & 0x1f;
936 l = c >> 5;
Damien Georgeb534e1b2014-09-04 14:44:01 +0100937 ip += 1;
Damien Georgeb427d6a2014-08-26 23:35:57 +0100938 } else {
939 // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
940 b = c & 0xf;
Damien Georgeb534e1b2014-09-04 14:44:01 +0100941 l = ((c << 4) & 0x700) | ip[1];
942 ip += 2;
Damien Georgeb427d6a2014-08-26 23:35:57 +0100943 }
944 if (bc >= b) {
945 bc -= b;
946 source_line += l;
947 } else {
948 // found source line corresponding to bytecode offset
949 break;
Paul Sokolovsky411732e2014-06-02 18:24:34 +0300950 }
Damien George08335002014-01-18 23:24:36 +0000951 }
Damien George136b1492014-01-19 12:38:49 +0000952 mp_obj_exception_add_traceback(nlr.ret_val, source_file, source_line, block_name);
Damien George08335002014-01-18 23:24:36 +0000953 }
954
Damien8f9e2ee2013-12-29 16:54:59 +0000955 while (currently_in_except_block) {
956 // nested exception
957
Paul Sokolovskyc0abc282014-03-22 13:49:31 +0200958 assert(exc_sp >= exc_stack);
Damien8f9e2ee2013-12-29 16:54:59 +0000959
960 // TODO make a proper message for nested exception
961 // at the moment we are just raising the very last exception (the one that caused the nested exception)
962
963 // move up to previous exception handler
Paul Sokolovskya0ad77b2014-03-29 23:16:27 +0200964 POP_EXC_BLOCK();
Damien8f9e2ee2013-12-29 16:54:59 +0000965 }
966
Paul Sokolovskyc0abc282014-03-22 13:49:31 +0200967 if (exc_sp >= exc_stack) {
Damien8f9e2ee2013-12-29 16:54:59 +0000968 // set flag to indicate that we are now handling an exception
969 currently_in_except_block = 1;
970
Damience89a212013-10-15 22:25:17 +0100971 // catch exception and pass to byte code
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300972 code_state->ip = exc_sp->handler;
Damien George66ae8c92014-04-17 16:50:23 +0100973 mp_obj_t *sp = MP_TAGPTR_PTR(exc_sp->val_sp);
Damien Georged7592a12014-03-30 00:54:48 +0000974 // save this exception in the stack so it can be used in a reraise, if needed
975 exc_sp->prev_exc = nlr.ret_val;
Damienc9f91972013-10-15 23:46:01 +0100976 // push(traceback, exc-val, exc-type)
Damiend99b0522013-12-21 18:17:45 +0000977 PUSH(mp_const_none);
Damienc9f91972013-10-15 23:46:01 +0100978 PUSH(nlr.ret_val);
Paul Sokolovsky682f9e62014-03-29 02:52:17 +0200979 PUSH(mp_obj_get_type(nlr.ret_val));
Paul Sokolovskyb4ebad32014-05-31 16:50:46 +0300980 code_state->sp = sp;
Damien8f9e2ee2013-12-29 16:54:59 +0000981
Damience89a212013-10-15 22:25:17 +0100982 } else {
Damien Georgec8f78bc2014-02-15 22:55:00 +0000983 // propagate exception to higher level
984 // TODO what to do about ip and sp? they don't really make sense at this point
985 fastn[0] = nlr.ret_val; // must put exception here because sp is invalid
986 return MP_VM_RETURN_EXCEPTION;
Damience89a212013-10-15 22:25:17 +0100987 }
Damien429d7192013-10-04 19:53:11 +0100988 }
989 }
990}