blob: 44cbd9f3597ecff58e07fb996a5789a192dee94d [file] [log] [blame]
Damien429d7192013-10-04 19:53:11 +01001#include <stdint.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <string.h>
5#include <assert.h>
6
Damience89a212013-10-15 22:25:17 +01007#include "nlr.h"
Damien429d7192013-10-04 19:53:11 +01008#include "misc.h"
Damiend99b0522013-12-21 18:17:45 +00009#include "mpconfig.h"
10#include "obj.h"
Damien429d7192013-10-04 19:53:11 +010011#include "runtime.h"
Damiend99b0522013-12-21 18:17:45 +000012#include "bc0.h"
Damieneb19efb2013-10-10 22:06:54 +010013#include "bc.h"
Damien429d7192013-10-04 19:53:11 +010014
Damienbd254452013-10-16 20:39:12 +010015// (value) stack grows down (to be compatible with native code when passing pointers to the stack), top element is pointed to
16// exception stack grows up, top element is pointed to
17
Damien429d7192013-10-04 19:53:11 +010018#define DECODE_UINT do { unum = *ip++; if (unum > 127) { unum = ((unum & 0x3f) << 8) | (*ip++); } } while (0)
Damien03c9cfb2013-11-05 22:06:08 +000019#define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0)
20#define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0)
Damien Georgecbd2f742014-01-19 11:48:48 +000021#define DECODE_QSTR do { qst = *ip++; if (qst > 127) { qst = ((qst & 0x3f) << 8) | (*ip++); } } while (0)
Damien George20006db2014-01-18 14:10:48 +000022#define PUSH(val) *++sp = (val)
23#define POP() (*sp--)
Damiendb4c3612013-12-10 17:27:24 +000024#define TOP() (*sp)
25#define SET_TOP(val) *sp = (val)
Damien429d7192013-10-04 19:53:11 +010026
Damiend99b0522013-12-21 18:17:45 +000027mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, uint n_state) {
Damien Georgee02b2d42014-01-19 01:14:37 +000028 n_state += 1; // XXX there is a bug somewhere which doesn't count enough state... (conwaylife and mandel have the bug)
29
Damien George20006db2014-01-18 14:10:48 +000030 // allocate state for locals and stack
31 mp_obj_t temp_state[10];
Damiend99b0522013-12-21 18:17:45 +000032 mp_obj_t *state = &temp_state[0];
Damien40fdfe32013-11-05 22:16:22 +000033 if (n_state > 10) {
Damiend99b0522013-12-21 18:17:45 +000034 state = m_new(mp_obj_t, n_state);
Damien40fdfe32013-11-05 22:16:22 +000035 }
Damien George20006db2014-01-18 14:10:48 +000036 mp_obj_t *sp = &state[0] - 1;
37
Damienbd254452013-10-16 20:39:12 +010038 // init args
39 for (int i = 0; i < n_args; i++) {
40 assert(i < 8);
Damien George20006db2014-01-18 14:10:48 +000041 state[n_state - 1 - i] = args[i];
Damienbd254452013-10-16 20:39:12 +010042 }
Damien George08335002014-01-18 23:24:36 +000043
Damienbd254452013-10-16 20:39:12 +010044 const byte *ip = code;
Damien George6baf76e2013-12-30 22:32:17 +000045
Damien George08335002014-01-18 23:24:36 +000046 // get code info size
47 machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
48 ip += code_info_size;
49
Damien George6baf76e2013-12-30 22:32:17 +000050 // execute prelude to make any cells (closed over variables)
51 {
52 for (uint n_local = *ip++; n_local > 0; n_local--) {
53 uint local_num = *ip++;
54 if (local_num < n_args) {
Damien George20006db2014-01-18 14:10:48 +000055 state[n_state - 1 - local_num] = mp_obj_new_cell(state[n_state - 1 - local_num]);
Damien George6baf76e2013-12-30 22:32:17 +000056 } else {
Damien George20006db2014-01-18 14:10:48 +000057 state[n_state - 1 - local_num] = mp_obj_new_cell(MP_OBJ_NULL);
Damien George6baf76e2013-12-30 22:32:17 +000058 }
59 }
60 }
61
62 // execute the byte code
Damien George08335002014-01-18 23:24:36 +000063 if (mp_execute_byte_code_2(code, &ip, &state[n_state - 1], &sp)) {
Damienbd254452013-10-16 20:39:12 +010064 // it shouldn't yield
65 assert(0);
66 }
Damien George6baf76e2013-12-30 22:32:17 +000067
Damien4ebb32f2013-11-02 14:33:10 +000068 // TODO check fails if, eg, return from within for loop
69 //assert(sp == &state[17]);
Damienbd254452013-10-16 20:39:12 +010070 return *sp;
71}
72
Damien George20006db2014-01-18 14:10:48 +000073// fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)
74// sp points to bottom of stack which grows up
Damien George08335002014-01-18 23:24:36 +000075bool mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out) {
Damienc9f91972013-10-15 23:46:01 +010076 // careful: be sure to declare volatile any variables read in the exception handler (written is ok, I think)
77
Damienbd254452013-10-16 20:39:12 +010078 const byte *ip = *ip_in_out;
Damiend99b0522013-12-21 18:17:45 +000079 mp_obj_t *sp = *sp_in_out;
Damien429d7192013-10-04 19:53:11 +010080 machine_uint_t unum;
Damien Georgecbd2f742014-01-19 11:48:48 +000081 qstr qst;
Damiend99b0522013-12-21 18:17:45 +000082 mp_obj_t obj1, obj2;
Damien George20006db2014-01-18 14:10:48 +000083 mp_obj_t fast0 = fastn[0], fast1 = fastn[-1], fast2 = fastn[-2];
Damience89a212013-10-15 22:25:17 +010084 nlr_buf_t nlr;
Damien429d7192013-10-04 19:53:11 +010085
Damien8f9e2ee2013-12-29 16:54:59 +000086 volatile machine_uint_t currently_in_except_block = 0; // 0 or 1, to detect nested exceptions
87 machine_uint_t exc_stack[8]; // on the exception stack we store (ip, sp | X) for each block, X = previous value of currently_in_except_block
Damien George66327002014-01-02 18:20:41 +000088 machine_uint_t *volatile exc_sp = &exc_stack[0] - 1; // stack grows up, exc_sp points to top of stack
Damien George08335002014-01-18 23:24:36 +000089 const byte *volatile save_ip = ip; // this is so we can access ip in the exception handler without making ip volatile (which means the compiler can't keep it in a register in the main loop)
Damienc9f91972013-10-15 23:46:01 +010090
Damien Georgee02b2d42014-01-19 01:14:37 +000091 // TODO if an exception occurs, do fast[0,1,2] become invalid??
92
Damience89a212013-10-15 22:25:17 +010093 // outer exception handling loop
Damien429d7192013-10-04 19:53:11 +010094 for (;;) {
Damience89a212013-10-15 22:25:17 +010095 if (nlr_push(&nlr) == 0) {
96 // loop to execute byte code
97 for (;;) {
Damien George08335002014-01-18 23:24:36 +000098 save_ip = ip;
Damience89a212013-10-15 22:25:17 +010099 int op = *ip++;
100 switch (op) {
Damiend99b0522013-12-21 18:17:45 +0000101 case MP_BC_LOAD_CONST_FALSE:
102 PUSH(mp_const_false);
Damience89a212013-10-15 22:25:17 +0100103 break;
Damien429d7192013-10-04 19:53:11 +0100104
Damiend99b0522013-12-21 18:17:45 +0000105 case MP_BC_LOAD_CONST_NONE:
106 PUSH(mp_const_none);
Damience89a212013-10-15 22:25:17 +0100107 break;
Damien429d7192013-10-04 19:53:11 +0100108
Damiend99b0522013-12-21 18:17:45 +0000109 case MP_BC_LOAD_CONST_TRUE:
110 PUSH(mp_const_true);
Damience89a212013-10-15 22:25:17 +0100111 break;
Damien429d7192013-10-04 19:53:11 +0100112
Damien Georgee9906ac2014-01-04 18:44:46 +0000113 case MP_BC_LOAD_CONST_ELLIPSIS:
114 PUSH(mp_const_ellipsis);
115 break;
116
Damiend99b0522013-12-21 18:17:45 +0000117 case MP_BC_LOAD_CONST_SMALL_INT:
Damien03c9cfb2013-11-05 22:06:08 +0000118 unum = (ip[0] | (ip[1] << 8) | (ip[2] << 16)) - 0x800000;
Damien6addc892013-11-04 23:04:50 +0000119 ip += 3;
Paul Sokolovskye5ee1692014-01-06 17:49:46 +0200120 PUSH(MP_OBJ_NEW_SMALL_INT(unum));
Damience89a212013-10-15 22:25:17 +0100121 break;
122
Paul Sokolovskya9f5abd2014-01-17 19:51:46 +0200123 case MP_BC_LOAD_CONST_INT:
124 DECODE_QSTR;
Damien Georgecbd2f742014-01-19 11:48:48 +0000125 PUSH(mp_obj_new_int_from_long_str(qstr_str(qst)));
Paul Sokolovskya9f5abd2014-01-17 19:51:46 +0200126 break;
127
Damiend99b0522013-12-21 18:17:45 +0000128 case MP_BC_LOAD_CONST_DEC:
Damien7410e442013-11-02 19:47:57 +0000129 DECODE_QSTR;
Damien Georgecbd2f742014-01-19 11:48:48 +0000130 PUSH(rt_load_const_dec(qst));
Damien7410e442013-11-02 19:47:57 +0000131 break;
132
Damiend99b0522013-12-21 18:17:45 +0000133 case MP_BC_LOAD_CONST_ID:
Damience89a212013-10-15 22:25:17 +0100134 DECODE_QSTR;
Damien Georgecbd2f742014-01-19 11:48:48 +0000135 PUSH(rt_load_const_str(qst)); // TODO
Damience89a212013-10-15 22:25:17 +0100136 break;
137
Paul Sokolovskybdf822b2014-01-02 18:46:27 +0200138 case MP_BC_LOAD_CONST_BYTES:
139 DECODE_QSTR;
Damien Georgecbd2f742014-01-19 11:48:48 +0000140 PUSH(rt_load_const_str(qst)); // TODO
Paul Sokolovskybdf822b2014-01-02 18:46:27 +0200141 break;
142
Damiend99b0522013-12-21 18:17:45 +0000143 case MP_BC_LOAD_CONST_STRING:
Damience89a212013-10-15 22:25:17 +0100144 DECODE_QSTR;
Damien Georgecbd2f742014-01-19 11:48:48 +0000145 PUSH(rt_load_const_str(qst));
Damience89a212013-10-15 22:25:17 +0100146 break;
147
Damiend99b0522013-12-21 18:17:45 +0000148 case MP_BC_LOAD_FAST_0:
Damience89a212013-10-15 22:25:17 +0100149 PUSH(fast0);
150 break;
151
Damiend99b0522013-12-21 18:17:45 +0000152 case MP_BC_LOAD_FAST_1:
Damience89a212013-10-15 22:25:17 +0100153 PUSH(fast1);
154 break;
155
Damiend99b0522013-12-21 18:17:45 +0000156 case MP_BC_LOAD_FAST_2:
Damience89a212013-10-15 22:25:17 +0100157 PUSH(fast2);
158 break;
159
Damiend99b0522013-12-21 18:17:45 +0000160 case MP_BC_LOAD_FAST_N:
Damience89a212013-10-15 22:25:17 +0100161 DECODE_UINT;
Damien George20006db2014-01-18 14:10:48 +0000162 PUSH(fastn[-unum]);
Damience89a212013-10-15 22:25:17 +0100163 break;
164
Damiend99b0522013-12-21 18:17:45 +0000165 case MP_BC_LOAD_DEREF:
Damien9ecbcff2013-12-11 00:41:43 +0000166 DECODE_UINT;
Damien George20006db2014-01-18 14:10:48 +0000167 if (unum == 0) {
168 obj1 = fast0;
169 } else if (unum == 1) {
170 obj1 = fast1;
171 } else if (unum == 2) {
172 obj1 = fast2;
173 } else {
174 obj1 = fastn[-unum];
175 }
176 PUSH(rt_get_cell(obj1));
Damien9ecbcff2013-12-11 00:41:43 +0000177 break;
178
Damiend99b0522013-12-21 18:17:45 +0000179 case MP_BC_LOAD_NAME:
Damience89a212013-10-15 22:25:17 +0100180 DECODE_QSTR;
Damien Georgecbd2f742014-01-19 11:48:48 +0000181 PUSH(rt_load_name(qst));
Damience89a212013-10-15 22:25:17 +0100182 break;
183
Damiend99b0522013-12-21 18:17:45 +0000184 case MP_BC_LOAD_GLOBAL:
Damience89a212013-10-15 22:25:17 +0100185 DECODE_QSTR;
Damien Georgecbd2f742014-01-19 11:48:48 +0000186 PUSH(rt_load_global(qst));
Damience89a212013-10-15 22:25:17 +0100187 break;
188
Damiend99b0522013-12-21 18:17:45 +0000189 case MP_BC_LOAD_ATTR:
Damience89a212013-10-15 22:25:17 +0100190 DECODE_QSTR;
Damien Georgecbd2f742014-01-19 11:48:48 +0000191 SET_TOP(rt_load_attr(TOP(), qst));
Damience89a212013-10-15 22:25:17 +0100192 break;
193
Damiend99b0522013-12-21 18:17:45 +0000194 case MP_BC_LOAD_METHOD:
Damience89a212013-10-15 22:25:17 +0100195 DECODE_QSTR;
Damien Georgecbd2f742014-01-19 11:48:48 +0000196 rt_load_method(*sp, qst, sp);
Damien George20006db2014-01-18 14:10:48 +0000197 sp += 1;
Damience89a212013-10-15 22:25:17 +0100198 break;
199
Damiend99b0522013-12-21 18:17:45 +0000200 case MP_BC_LOAD_BUILD_CLASS:
Damience89a212013-10-15 22:25:17 +0100201 PUSH(rt_load_build_class());
202 break;
203
Damiend99b0522013-12-21 18:17:45 +0000204 case MP_BC_STORE_FAST_0:
Damience89a212013-10-15 22:25:17 +0100205 fast0 = POP();
206 break;
207
Damiend99b0522013-12-21 18:17:45 +0000208 case MP_BC_STORE_FAST_1:
Damience89a212013-10-15 22:25:17 +0100209 fast1 = POP();
210 break;
211
Damiend99b0522013-12-21 18:17:45 +0000212 case MP_BC_STORE_FAST_2:
Damience89a212013-10-15 22:25:17 +0100213 fast2 = POP();
214 break;
215
Damiend99b0522013-12-21 18:17:45 +0000216 case MP_BC_STORE_FAST_N:
Damience89a212013-10-15 22:25:17 +0100217 DECODE_UINT;
Damien George20006db2014-01-18 14:10:48 +0000218 fastn[-unum] = POP();
Damience89a212013-10-15 22:25:17 +0100219 break;
220
Damiend99b0522013-12-21 18:17:45 +0000221 case MP_BC_STORE_DEREF:
Damien9ecbcff2013-12-11 00:41:43 +0000222 DECODE_UINT;
Damien George20006db2014-01-18 14:10:48 +0000223 if (unum == 0) {
224 obj1 = fast0;
225 } else if (unum == 1) {
226 obj1 = fast1;
227 } else if (unum == 2) {
228 obj1 = fast2;
229 } else {
230 obj1 = fastn[-unum];
231 }
232 rt_set_cell(obj1, POP());
Damien9ecbcff2013-12-11 00:41:43 +0000233 break;
234
Damiend99b0522013-12-21 18:17:45 +0000235 case MP_BC_STORE_NAME:
Damience89a212013-10-15 22:25:17 +0100236 DECODE_QSTR;
Damien Georgecbd2f742014-01-19 11:48:48 +0000237 rt_store_name(qst, POP());
Damience89a212013-10-15 22:25:17 +0100238 break;
239
Damiend99b0522013-12-21 18:17:45 +0000240 case MP_BC_STORE_GLOBAL:
Damien6addc892013-11-04 23:04:50 +0000241 DECODE_QSTR;
Damien Georgecbd2f742014-01-19 11:48:48 +0000242 rt_store_global(qst, POP());
Damien6addc892013-11-04 23:04:50 +0000243 break;
244
Damiend99b0522013-12-21 18:17:45 +0000245 case MP_BC_STORE_ATTR:
Damience89a212013-10-15 22:25:17 +0100246 DECODE_QSTR;
Damien Georgecbd2f742014-01-19 11:48:48 +0000247 rt_store_attr(sp[0], qst, sp[-1]);
Damien George20006db2014-01-18 14:10:48 +0000248 sp -= 2;
Damience89a212013-10-15 22:25:17 +0100249 break;
250
Damiend99b0522013-12-21 18:17:45 +0000251 case MP_BC_STORE_SUBSCR:
Damien George20006db2014-01-18 14:10:48 +0000252 rt_store_subscr(sp[-1], sp[0], sp[-2]);
253 sp -= 3;
Damience89a212013-10-15 22:25:17 +0100254 break;
255
Damiend99b0522013-12-21 18:17:45 +0000256 case MP_BC_DUP_TOP:
Damiendb4c3612013-12-10 17:27:24 +0000257 obj1 = TOP();
Damience89a212013-10-15 22:25:17 +0100258 PUSH(obj1);
259 break;
260
Damiend99b0522013-12-21 18:17:45 +0000261 case MP_BC_DUP_TOP_TWO:
Damien George20006db2014-01-18 14:10:48 +0000262 sp += 2;
263 sp[0] = sp[-2];
264 sp[-1] = sp[-3];
Damience89a212013-10-15 22:25:17 +0100265 break;
266
Damiend99b0522013-12-21 18:17:45 +0000267 case MP_BC_POP_TOP:
Damien George20006db2014-01-18 14:10:48 +0000268 sp -= 1;
Damience89a212013-10-15 22:25:17 +0100269 break;
270
Damiend99b0522013-12-21 18:17:45 +0000271 case MP_BC_ROT_TWO:
Damien4ebb32f2013-11-02 14:33:10 +0000272 obj1 = sp[0];
Damien George20006db2014-01-18 14:10:48 +0000273 sp[0] = sp[-1];
274 sp[-1] = obj1;
Damien4ebb32f2013-11-02 14:33:10 +0000275 break;
276
Damiend99b0522013-12-21 18:17:45 +0000277 case MP_BC_ROT_THREE:
Damience89a212013-10-15 22:25:17 +0100278 obj1 = sp[0];
Damien George20006db2014-01-18 14:10:48 +0000279 sp[0] = sp[-1];
280 sp[-1] = sp[-2];
281 sp[-2] = obj1;
Damience89a212013-10-15 22:25:17 +0100282 break;
283
Damiend99b0522013-12-21 18:17:45 +0000284 case MP_BC_JUMP:
Damien03c9cfb2013-11-05 22:06:08 +0000285 DECODE_SLABEL;
286 ip += unum;
Damience89a212013-10-15 22:25:17 +0100287 break;
288
Damiend99b0522013-12-21 18:17:45 +0000289 case MP_BC_POP_JUMP_IF_TRUE:
Damien03c9cfb2013-11-05 22:06:08 +0000290 DECODE_SLABEL;
Damience89a212013-10-15 22:25:17 +0100291 if (rt_is_true(POP())) {
Damien03c9cfb2013-11-05 22:06:08 +0000292 ip += unum;
Damience89a212013-10-15 22:25:17 +0100293 }
294 break;
295
Damiend99b0522013-12-21 18:17:45 +0000296 case MP_BC_POP_JUMP_IF_FALSE:
Damien03c9cfb2013-11-05 22:06:08 +0000297 DECODE_SLABEL;
Damience89a212013-10-15 22:25:17 +0100298 if (!rt_is_true(POP())) {
Damien03c9cfb2013-11-05 22:06:08 +0000299 ip += unum;
Damience89a212013-10-15 22:25:17 +0100300 }
301 break;
302
Damiend99b0522013-12-21 18:17:45 +0000303 case MP_BC_JUMP_IF_TRUE_OR_POP:
Damien94658e22013-11-09 20:12:32 +0000304 DECODE_SLABEL;
Damiendb4c3612013-12-10 17:27:24 +0000305 if (rt_is_true(TOP())) {
Damien94658e22013-11-09 20:12:32 +0000306 ip += unum;
307 } else {
Damien George20006db2014-01-18 14:10:48 +0000308 sp--;
Damien94658e22013-11-09 20:12:32 +0000309 }
310 break;
311
Damiend99b0522013-12-21 18:17:45 +0000312 case MP_BC_JUMP_IF_FALSE_OR_POP:
Damien94658e22013-11-09 20:12:32 +0000313 DECODE_SLABEL;
Damiendb4c3612013-12-10 17:27:24 +0000314 if (rt_is_true(TOP())) {
Damien George20006db2014-01-18 14:10:48 +0000315 sp--;
Damien94658e22013-11-09 20:12:32 +0000316 } else {
317 ip += unum;
318 }
319 break;
320
Damience89a212013-10-15 22:25:17 +0100321 /* we are trying to get away without using this opcode
Damiend99b0522013-12-21 18:17:45 +0000322 case MP_BC_SETUP_LOOP:
Damience89a212013-10-15 22:25:17 +0100323 DECODE_UINT;
Damiend99b0522013-12-21 18:17:45 +0000324 // push_block(MP_BC_SETUP_LOOP, ip + unum, sp)
Damience89a212013-10-15 22:25:17 +0100325 break;
326 */
327
Damien02a7c412013-12-29 18:48:37 +0000328 // matched against: POP_BLOCK or POP_EXCEPT (anything else?)
Damiend99b0522013-12-21 18:17:45 +0000329 case MP_BC_SETUP_EXCEPT:
Damien03c9cfb2013-11-05 22:06:08 +0000330 DECODE_ULABEL; // except labels are always forward
331 *++exc_sp = (machine_uint_t)ip + unum;
Damien8f9e2ee2013-12-29 16:54:59 +0000332 *++exc_sp = (((machine_uint_t)sp) | currently_in_except_block);
333 currently_in_except_block = 0; // in a try block now
Damience89a212013-10-15 22:25:17 +0100334 break;
335
Damiend99b0522013-12-21 18:17:45 +0000336 case MP_BC_END_FINALLY:
Damience89a212013-10-15 22:25:17 +0100337 // not implemented
338 // if TOS is an exception, reraises the exception (3 values on TOS)
339 // if TOS is an integer, does something else
340 // if TOS is None, just pops it and continues
341 // else error
342 assert(0);
343 break;
344
Damiend99b0522013-12-21 18:17:45 +0000345 case MP_BC_GET_ITER:
Damiendb4c3612013-12-10 17:27:24 +0000346 SET_TOP(rt_getiter(TOP()));
Damience89a212013-10-15 22:25:17 +0100347 break;
348
Damiend99b0522013-12-21 18:17:45 +0000349 case MP_BC_FOR_ITER:
Damien03c9cfb2013-11-05 22:06:08 +0000350 DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
Damiendb4c3612013-12-10 17:27:24 +0000351 obj1 = rt_iternext(TOP());
Damiend99b0522013-12-21 18:17:45 +0000352 if (obj1 == mp_const_stop_iteration) {
Damien George20006db2014-01-18 14:10:48 +0000353 --sp; // pop the exhausted iterator
Damien03c9cfb2013-11-05 22:06:08 +0000354 ip += unum; // jump to after for-block
Damience89a212013-10-15 22:25:17 +0100355 } else {
356 PUSH(obj1); // push the next iteration value
357 }
358 break;
359
Damien02a7c412013-12-29 18:48:37 +0000360 // matched against: SETUP_EXCEPT, SETUP_FINALLY, SETUP_WITH
Damiend99b0522013-12-21 18:17:45 +0000361 case MP_BC_POP_BLOCK:
Damien02a7c412013-12-29 18:48:37 +0000362 // we are exiting an exception handler, so pop the last one of the exception-stack
363 assert(exc_sp >= &exc_stack[0]);
364 currently_in_except_block = (exc_sp[0] & 1); // restore previous state
365 exc_sp -= 2; // pop back to previous exception handler
Damience89a212013-10-15 22:25:17 +0100366 break;
367
Damien02a7c412013-12-29 18:48:37 +0000368 // matched againts: SETUP_EXCEPT
Damiend99b0522013-12-21 18:17:45 +0000369 case MP_BC_POP_EXCEPT:
Damienc9f91972013-10-15 23:46:01 +0100370 // TODO need to work out how blocks work etc
Damience89a212013-10-15 22:25:17 +0100371 // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
Damienc9f91972013-10-15 23:46:01 +0100372 assert(exc_sp >= &exc_stack[0]);
Damiend99b0522013-12-21 18:17:45 +0000373 //sp = (mp_obj_t*)(*exc_sp--);
Damienc9f91972013-10-15 23:46:01 +0100374 //exc_sp--; // discard ip
Damien8f9e2ee2013-12-29 16:54:59 +0000375 currently_in_except_block = (exc_sp[0] & 1); // restore previous state
376 exc_sp -= 2; // pop back to previous exception handler
Damien George20006db2014-01-18 14:10:48 +0000377 //sp -= 3; // pop 3 exception values
Damience89a212013-10-15 22:25:17 +0100378 break;
379
Damiend99b0522013-12-21 18:17:45 +0000380 case MP_BC_UNARY_OP:
Damien7410e442013-11-02 19:47:57 +0000381 unum = *ip++;
Damiendb4c3612013-12-10 17:27:24 +0000382 SET_TOP(rt_unary_op(unum, TOP()));
Damien7410e442013-11-02 19:47:57 +0000383 break;
384
Damiend99b0522013-12-21 18:17:45 +0000385 case MP_BC_BINARY_OP:
Damience89a212013-10-15 22:25:17 +0100386 unum = *ip++;
387 obj2 = POP();
Damiendb4c3612013-12-10 17:27:24 +0000388 obj1 = TOP();
389 SET_TOP(rt_binary_op(unum, obj1, obj2));
Damience89a212013-10-15 22:25:17 +0100390 break;
391
Damiend99b0522013-12-21 18:17:45 +0000392 case MP_BC_BUILD_TUPLE:
Damienc226dca2013-10-16 16:12:52 +0100393 DECODE_UINT;
Damien George20006db2014-01-18 14:10:48 +0000394 sp -= unum - 1;
395 SET_TOP(rt_build_tuple(unum, sp));
Damienc226dca2013-10-16 16:12:52 +0100396 break;
397
Damiend99b0522013-12-21 18:17:45 +0000398 case MP_BC_BUILD_LIST:
Damience89a212013-10-15 22:25:17 +0100399 DECODE_UINT;
Damien George20006db2014-01-18 14:10:48 +0000400 sp -= unum - 1;
401 SET_TOP(rt_build_list(unum, sp));
Damience89a212013-10-15 22:25:17 +0100402 break;
403
Damiend99b0522013-12-21 18:17:45 +0000404 case MP_BC_LIST_APPEND:
Damienc226dca2013-10-16 16:12:52 +0100405 DECODE_UINT;
406 // I think it's guaranteed by the compiler that sp[unum] is a list
Damien George20006db2014-01-18 14:10:48 +0000407 rt_list_append(sp[-unum], sp[0]);
408 sp--;
Damienc226dca2013-10-16 16:12:52 +0100409 break;
410
Damiend99b0522013-12-21 18:17:45 +0000411 case MP_BC_BUILD_MAP:
Damience89a212013-10-15 22:25:17 +0100412 DECODE_UINT;
413 PUSH(rt_build_map(unum));
414 break;
415
Damiend99b0522013-12-21 18:17:45 +0000416 case MP_BC_STORE_MAP:
Damien George20006db2014-01-18 14:10:48 +0000417 sp -= 2;
418 rt_store_map(sp[0], sp[2], sp[1]);
Damience89a212013-10-15 22:25:17 +0100419 break;
420
Damiend99b0522013-12-21 18:17:45 +0000421 case MP_BC_MAP_ADD:
Damien5fd09662013-10-16 20:54:01 +0100422 DECODE_UINT;
Damien George20006db2014-01-18 14:10:48 +0000423 // I think it's guaranteed by the compiler that sp[-unum - 1] is a map
424 rt_store_map(sp[-unum - 1], sp[0], sp[-1]);
425 sp -= 2;
Damien5fd09662013-10-16 20:54:01 +0100426 break;
427
Damiend99b0522013-12-21 18:17:45 +0000428 case MP_BC_BUILD_SET:
Damience89a212013-10-15 22:25:17 +0100429 DECODE_UINT;
Damien George20006db2014-01-18 14:10:48 +0000430 sp -= unum - 1;
431 SET_TOP(rt_build_set(unum, sp));
Damience89a212013-10-15 22:25:17 +0100432 break;
433
Damiend99b0522013-12-21 18:17:45 +0000434 case MP_BC_SET_ADD:
Damienc12aa462013-10-16 20:57:49 +0100435 DECODE_UINT;
Damien George20006db2014-01-18 14:10:48 +0000436 // I think it's guaranteed by the compiler that sp[-unum] is a set
437 rt_store_set(sp[-unum], sp[0]);
438 sp--;
Damienc12aa462013-10-16 20:57:49 +0100439 break;
440
Paul Sokolovskye606cb62014-01-04 01:34:23 +0200441#if MICROPY_ENABLE_SLICE
Paul Sokolovskyded0a1e2014-01-03 02:48:56 +0200442 case MP_BC_BUILD_SLICE:
443 DECODE_UINT;
444 if (unum == 2) {
445 obj2 = POP();
446 obj1 = TOP();
447 SET_TOP(mp_obj_new_slice(obj1, obj2, NULL));
448 } else {
449 printf("3-argument slice is not supported\n");
450 assert(0);
451 }
452 break;
Paul Sokolovskye606cb62014-01-04 01:34:23 +0200453#endif
Paul Sokolovskyded0a1e2014-01-03 02:48:56 +0200454
Damiend99b0522013-12-21 18:17:45 +0000455 case MP_BC_UNPACK_SEQUENCE:
Damien6f3e7fc2013-11-26 15:15:50 +0000456 DECODE_UINT;
Damien George932bf1c2014-01-18 23:42:49 +0000457 rt_unpack_sequence(sp[0], unum, sp);
Damien George20006db2014-01-18 14:10:48 +0000458 sp += unum - 1;
Damien6f3e7fc2013-11-26 15:15:50 +0000459 break;
460
Damiend99b0522013-12-21 18:17:45 +0000461 case MP_BC_MAKE_FUNCTION:
Damience89a212013-10-15 22:25:17 +0100462 DECODE_UINT;
463 PUSH(rt_make_function_from_id(unum));
464 break;
465
Damiend99b0522013-12-21 18:17:45 +0000466 case MP_BC_MAKE_CLOSURE:
Damien9ecbcff2013-12-11 00:41:43 +0000467 DECODE_UINT;
468 obj1 = POP();
469 PUSH(rt_make_closure_from_id(unum, obj1));
470 break;
471
Damiend99b0522013-12-21 18:17:45 +0000472 case MP_BC_CALL_FUNCTION:
Damience89a212013-10-15 22:25:17 +0100473 DECODE_UINT;
Damien George20006db2014-01-18 14:10:48 +0000474 // unum & 0xff == n_positional
475 // (unum >> 8) & 0xff == n_keyword
476 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe);
477 SET_TOP(rt_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
Damience89a212013-10-15 22:25:17 +0100478 break;
479
Damiend99b0522013-12-21 18:17:45 +0000480 case MP_BC_CALL_METHOD:
Damience89a212013-10-15 22:25:17 +0100481 DECODE_UINT;
Damien George20006db2014-01-18 14:10:48 +0000482 // unum & 0xff == n_positional
483 // (unum >> 8) & 0xff == n_keyword
484 sp -= (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
485 SET_TOP(rt_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
Damience89a212013-10-15 22:25:17 +0100486 break;
487
Damiend99b0522013-12-21 18:17:45 +0000488 case MP_BC_RETURN_VALUE:
Damience89a212013-10-15 22:25:17 +0100489 nlr_pop();
Damienbd254452013-10-16 20:39:12 +0100490 *sp_in_out = sp;
Damien George66327002014-01-02 18:20:41 +0000491 assert(exc_sp == &exc_stack[0] - 1);
Damienbd254452013-10-16 20:39:12 +0100492 return false;
493
Paul Sokolovsky5388a3c2014-01-10 16:09:55 +0200494 case MP_BC_RAISE_VARARGS:
495 unum = *ip++;
496 assert(unum == 1);
497 obj1 = POP();
498 nlr_jump(obj1);
Paul Sokolovsky5388a3c2014-01-10 16:09:55 +0200499
Damiend99b0522013-12-21 18:17:45 +0000500 case MP_BC_YIELD_VALUE:
Damienbd254452013-10-16 20:39:12 +0100501 nlr_pop();
502 *ip_in_out = ip;
503 fastn[0] = fast0;
Damien George20006db2014-01-18 14:10:48 +0000504 fastn[-1] = fast1;
505 fastn[-2] = fast2;
Damienbd254452013-10-16 20:39:12 +0100506 *sp_in_out = sp;
507 return true;
Damience89a212013-10-15 22:25:17 +0100508
Damiend99b0522013-12-21 18:17:45 +0000509 case MP_BC_IMPORT_NAME:
Damiendb4c3612013-12-10 17:27:24 +0000510 DECODE_QSTR;
511 obj1 = POP();
Damien Georgecbd2f742014-01-19 11:48:48 +0000512 SET_TOP(rt_import_name(qst, obj1, TOP()));
Damiendb4c3612013-12-10 17:27:24 +0000513 break;
514
Damiend99b0522013-12-21 18:17:45 +0000515 case MP_BC_IMPORT_FROM:
Damiendb4c3612013-12-10 17:27:24 +0000516 DECODE_QSTR;
Damien Georgecbd2f742014-01-19 11:48:48 +0000517 obj1 = rt_import_from(TOP(), qst);
Damiendb4c3612013-12-10 17:27:24 +0000518 PUSH(obj1);
519 break;
520
Damience89a212013-10-15 22:25:17 +0100521 default:
Damien03c9cfb2013-11-05 22:06:08 +0000522 printf("code %p, byte code 0x%02x not implemented\n", ip, op);
Damience89a212013-10-15 22:25:17 +0100523 assert(0);
524 nlr_pop();
Damienbd254452013-10-16 20:39:12 +0100525 return false;
Damien429d7192013-10-04 19:53:11 +0100526 }
Damience89a212013-10-15 22:25:17 +0100527 }
Damien429d7192013-10-04 19:53:11 +0100528
Damience89a212013-10-15 22:25:17 +0100529 } else {
530 // exception occurred
Damien429d7192013-10-04 19:53:11 +0100531
Damien George08335002014-01-18 23:24:36 +0000532 // set file and line number that the exception occurred at
533 if (MP_OBJ_IS_TYPE(nlr.ret_val, &exception_type)) {
534 machine_uint_t code_info_size = code_info[0] | (code_info[1] << 8) | (code_info[2] << 16) | (code_info[3] << 24);
Damien Georgecbd2f742014-01-19 11:48:48 +0000535 qstr source_file = code_info[4] | (code_info[5] << 8) | (code_info[6] << 16) | (code_info[7] << 24);
536 qstr block_name = code_info[8] | (code_info[9] << 8) | (code_info[10] << 16) | (code_info[11] << 24);
Damien George08335002014-01-18 23:24:36 +0000537 machine_uint_t source_line = 1;
538 machine_uint_t bc = save_ip - code_info - code_info_size;
Damien Georgecbd2f742014-01-19 11:48:48 +0000539 //printf("find %lu %d %d\n", bc, code_info[12], code_info[13]);
540 for (const byte* ci = code_info + 12; bc >= ci[0]; ci += 2) {
Damien George08335002014-01-18 23:24:36 +0000541 bc -= ci[0];
542 source_line += ci[1];
543 if (ci[0] == 0 && ci[1] == 0) {
544 break;
545 }
546 }
Damien Georgecbd2f742014-01-19 11:48:48 +0000547 mp_obj_exception_set_source_info(nlr.ret_val, source_file, source_line, block_name);
Damien George08335002014-01-18 23:24:36 +0000548 }
549
Damien8f9e2ee2013-12-29 16:54:59 +0000550 while (currently_in_except_block) {
551 // nested exception
552
553 assert(exc_sp >= &exc_stack[0]);
554
555 // TODO make a proper message for nested exception
556 // at the moment we are just raising the very last exception (the one that caused the nested exception)
557
558 // move up to previous exception handler
559 currently_in_except_block = (exc_sp[0] & 1); // restore previous state
560 exc_sp -= 2; // pop back to previous exception handler
561 }
562
Damienc9f91972013-10-15 23:46:01 +0100563 if (exc_sp >= &exc_stack[0]) {
Damien8f9e2ee2013-12-29 16:54:59 +0000564 // set flag to indicate that we are now handling an exception
565 currently_in_except_block = 1;
566
Damience89a212013-10-15 22:25:17 +0100567 // catch exception and pass to byte code
Damien8f9e2ee2013-12-29 16:54:59 +0000568 sp = (mp_obj_t*)(exc_sp[0] & (~((machine_uint_t)1)));
Damienc9f91972013-10-15 23:46:01 +0100569 ip = (const byte*)(exc_sp[-1]);
570 // push(traceback, exc-val, exc-type)
Damiend99b0522013-12-21 18:17:45 +0000571 PUSH(mp_const_none);
Damienc9f91972013-10-15 23:46:01 +0100572 PUSH(nlr.ret_val);
Damienb86e3f92013-12-29 17:17:43 +0000573 PUSH(nlr.ret_val); // TODO should be type(nlr.ret_val), I think...
Damien8f9e2ee2013-12-29 16:54:59 +0000574
Damience89a212013-10-15 22:25:17 +0100575 } else {
Damien8f9e2ee2013-12-29 16:54:59 +0000576 // re-raise exception to higher level
Damienbd254452013-10-16 20:39:12 +0100577 // TODO what to do if this is a generator??
Damience89a212013-10-15 22:25:17 +0100578 nlr_jump(nlr.ret_val);
579 }
Damien429d7192013-10-04 19:53:11 +0100580 }
581 }
582}