blob: 121cfa04e08c6dbe3691f54792d7880107476fa7 [file] [log] [blame]
Damien429d7192013-10-04 19:53:11 +01001#include <stdio.h>
2#include <string.h>
3#include <assert.h>
4
Damience89a212013-10-15 22:25:17 +01005#include "nlr.h"
Damien429d7192013-10-04 19:53:11 +01006#include "misc.h"
Damiend99b0522013-12-21 18:17:45 +00007#include "mpconfig.h"
Damien George55baff42014-01-21 21:40:13 +00008#include "qstr.h"
Damien660365e2013-12-17 18:27:24 +00009#include "obj.h"
Damien Georgecaac5422014-03-25 14:18:18 +000010#include "objmodule.h"
Damien George20773972014-02-22 18:12:43 +000011#include "parsenum.h"
Damiend99b0522013-12-21 18:17:45 +000012#include "runtime0.h"
13#include "runtime.h"
Damien George2326d522014-03-27 23:26:35 +000014#include "emitglue.h"
Damiend99b0522013-12-21 18:17:45 +000015#include "map.h"
Damien660365e2013-12-17 18:27:24 +000016#include "builtin.h"
Damien Georgecaac5422014-03-25 14:18:18 +000017#include "builtintables.h"
Damien George5fa93b62014-01-22 14:35:10 +000018#include "bc.h"
Rachel Dowdallcde86312014-03-22 17:29:27 +000019#include "intdivmod.h"
Damien660365e2013-12-17 18:27:24 +000020
Damien7f5dacf2013-10-10 11:24:39 +010021#if 0 // print debugging info
Damiena1ddfcc2013-10-10 23:25:50 +010022#define DEBUG_PRINT (1)
Paul Sokolovsky44739e22014-02-16 18:11:42 +020023#define DEBUG_printf DEBUG_printf
Damien George41eb6082014-02-26 22:40:35 +000024#define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__)
Damien7f5dacf2013-10-10 11:24:39 +010025#else // don't print debugging info
Damien George41eb6082014-02-26 22:40:35 +000026#define DEBUG_printf(...) (void)0
27#define DEBUG_OP_printf(...) (void)0
Damien7f5dacf2013-10-10 11:24:39 +010028#endif
Damien429d7192013-10-04 19:53:11 +010029
Damieneb19efb2013-10-10 22:06:54 +010030// locals and globals need to be pointers because they can be the same in outer module scope
Paul Sokolovsky520e2f52014-02-12 18:31:30 +020031STATIC mp_map_t *map_locals;
32STATIC mp_map_t *map_globals;
33STATIC mp_map_t map_builtins;
Damienbd254452013-10-16 20:39:12 +010034
Damien George38a2da62014-01-08 17:33:12 +000035// a good optimising compiler will inline this if necessary
Paul Sokolovsky520e2f52014-02-12 18:31:30 +020036STATIC void mp_map_add_qstr(mp_map_t *map, qstr qstr, mp_obj_t value) {
Damien George38a2da62014-01-08 17:33:12 +000037 mp_map_lookup(map, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
38}
39
Damien8b3a7c22013-10-23 20:20:17 +010040void rt_init(void) {
Damien George2326d522014-03-27 23:26:35 +000041 mp_emit_glue_init();
42
Damieneb19efb2013-10-10 22:06:54 +010043 // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
Damien George38a2da62014-01-08 17:33:12 +000044 map_locals = map_globals = mp_map_new(1);
Damien429d7192013-10-04 19:53:11 +010045
Damienb86e3f92013-12-29 17:17:43 +000046 // init built-in hash table
Damien George38a2da62014-01-08 17:33:12 +000047 mp_map_init(&map_builtins, 3);
Damienb86e3f92013-12-29 17:17:43 +000048
Damien Georgecaac5422014-03-25 14:18:18 +000049 // init global module stuff
50 mp_module_init();
Damien George0d028742014-01-22 23:59:20 +000051
Damien Georgecaac5422014-03-25 14:18:18 +000052 // add some builtins that can't be done in ROM
53 mp_map_add_qstr(map_globals, MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR___main__));
Damien Georgee9906ac2014-01-04 18:44:46 +000054
Paul Sokolovskydcac8802014-01-16 19:19:50 +020055#if MICROPY_CPYTHON_COMPAT
Paul Sokolovsky159c0f72014-01-20 01:57:20 +020056 // Precreate sys module, so "import sys" didn't throw exceptions.
Paul Sokolovskye11b17c2014-02-05 00:47:06 +020057 mp_obj_t m_sys = mp_obj_new_module(MP_QSTR_sys);
58 // Avoid warning of unused var
59 (void)m_sys;
Paul Sokolovskydcac8802014-01-16 19:19:50 +020060#endif
Paul Sokolovskye11b17c2014-02-05 00:47:06 +020061 // init sys.path
62 // for efficiency, left to platform-specific startup code
63 //sys_path = mp_obj_new_list(0, NULL);
64 //rt_store_attr(m_sys, MP_QSTR_path, sys_path);
Damien429d7192013-10-04 19:53:11 +010065}
66
Damien8b3a7c22013-10-23 20:20:17 +010067void rt_deinit(void) {
Damien George2326d522014-03-27 23:26:35 +000068 mp_map_free(map_globals);
69 mp_map_deinit(&map_builtins);
70 mp_module_deinit();
71 mp_emit_glue_deinit();
Damien429d7192013-10-04 19:53:11 +010072}
73
Damiend99b0522013-12-21 18:17:45 +000074int rt_is_true(mp_obj_t arg) {
75 DEBUG_OP_printf("is true %p\n", arg);
Damien George09a0c642014-01-30 10:05:33 +000076 if (arg == mp_const_false) {
77 return 0;
78 } else if (arg == mp_const_true) {
79 return 1;
80 } else if (arg == mp_const_none) {
81 return 0;
82 } else if (MP_OBJ_IS_SMALL_INT(arg)) {
Damiend99b0522013-12-21 18:17:45 +000083 if (MP_OBJ_SMALL_INT_VALUE(arg) == 0) {
84 return 0;
85 } else {
86 return 1;
87 }
Damiend99b0522013-12-21 18:17:45 +000088 } else {
Paul Sokolovskyc1d9bbc2014-01-30 04:37:19 +020089 mp_obj_type_t *type = mp_obj_get_type(arg);
90 if (type->unary_op != NULL) {
91 mp_obj_t result = type->unary_op(RT_UNARY_OP_BOOL, arg);
Damien George09a0c642014-01-30 10:05:33 +000092 if (result != MP_OBJ_NULL) {
Paul Sokolovskyc1d9bbc2014-01-30 04:37:19 +020093 return result == mp_const_true;
94 }
95 }
96
Damien Georgee4b6a072014-01-28 23:27:35 +000097 mp_obj_t len = mp_obj_len_maybe(arg);
98 if (len != MP_OBJ_NULL) {
99 // obj has a length, truth determined if len != 0
100 return len != MP_OBJ_NEW_SMALL_INT(0);
101 } else {
Paul Sokolovskyc1d9bbc2014-01-30 04:37:19 +0200102 // any other obj is true per Python semantics
Damien Georgee4b6a072014-01-28 23:27:35 +0000103 return 1;
104 }
Damiend99b0522013-12-21 18:17:45 +0000105 }
106}
107
108mp_obj_t rt_list_append(mp_obj_t self_in, mp_obj_t arg) {
109 return mp_obj_list_append(self_in, arg);
110}
111
Damiend99b0522013-12-21 18:17:45 +0000112mp_obj_t rt_load_const_dec(qstr qstr) {
Damien7410e442013-11-02 19:47:57 +0000113 DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
Damien George20773972014-02-22 18:12:43 +0000114 uint len;
115 const byte* data = qstr_data(qstr, &len);
Damien George6e48f7f2014-03-21 11:45:46 +0000116 return mp_parse_num_decimal((const char*)data, len, true, false);
Damien7410e442013-11-02 19:47:57 +0000117}
118
Damiend99b0522013-12-21 18:17:45 +0000119mp_obj_t rt_load_const_str(qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100120 DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
Damien George5fa93b62014-01-22 14:35:10 +0000121 return MP_OBJ_NEW_QSTR(qstr);
Damien429d7192013-10-04 19:53:11 +0100122}
123
Paul Sokolovsky91fb1c92014-01-24 22:50:40 +0200124mp_obj_t rt_load_const_bytes(qstr qstr) {
125 DEBUG_OP_printf("load b'%s'\n", qstr_str(qstr));
126 uint len;
127 const byte *data = qstr_data(qstr, &len);
128 return mp_obj_new_bytes(data, len);
129}
130
Damiend99b0522013-12-21 18:17:45 +0000131mp_obj_t rt_load_name(qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100132 // logic: search locals, globals, builtins
Damiena3977762013-10-09 23:10:10 +0100133 DEBUG_OP_printf("load name %s\n", qstr_str(qstr));
Damien George38a2da62014-01-08 17:33:12 +0000134 mp_map_elem_t *elem = mp_map_lookup(map_locals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP);
Damien Georgeaea532e2014-02-06 22:57:51 +0000135 if (elem != NULL) {
136 return elem->value;
137 } else {
138 return rt_load_global(qstr);
Damiena3977762013-10-09 23:10:10 +0100139 }
Damiena3977762013-10-09 23:10:10 +0100140}
141
Damiend99b0522013-12-21 18:17:45 +0000142mp_obj_t rt_load_global(qstr qstr) {
Damiena3977762013-10-09 23:10:10 +0100143 // logic: search globals, builtins
144 DEBUG_OP_printf("load global %s\n", qstr_str(qstr));
Damien George38a2da62014-01-08 17:33:12 +0000145 mp_map_elem_t *elem = mp_map_lookup(map_globals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP);
Damien429d7192013-10-04 19:53:11 +0100146 if (elem == NULL) {
Damien George38a2da62014-01-08 17:33:12 +0000147 elem = mp_map_lookup(&map_builtins, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP);
Damien429d7192013-10-04 19:53:11 +0100148 if (elem == NULL) {
Damien Georgecaac5422014-03-25 14:18:18 +0000149 mp_obj_t o = mp_builtin_tables_lookup_object(qstr);
150 if (o != MP_OBJ_NULL) {
151 return o;
Damien Georgeaea532e2014-02-06 22:57:51 +0000152 }
Damien Georgec5966122014-02-15 16:10:44 +0000153 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_NameError, "name '%s' is not defined", qstr_str(qstr)));
Damien429d7192013-10-04 19:53:11 +0100154 }
155 }
156 return elem->value;
157}
158
Damiend99b0522013-12-21 18:17:45 +0000159mp_obj_t rt_load_build_class(void) {
Damien429d7192013-10-04 19:53:11 +0100160 DEBUG_OP_printf("load_build_class\n");
Damien Georgecaac5422014-03-25 14:18:18 +0000161 // lookup __build_class__ in dynamic table of builtins first
Damien George38a2da62014-01-08 17:33:12 +0000162 mp_map_elem_t *elem = mp_map_lookup(&map_builtins, MP_OBJ_NEW_QSTR(MP_QSTR___build_class__), MP_MAP_LOOKUP);
Damien Georgeaea532e2014-02-06 22:57:51 +0000163 if (elem != NULL) {
Damien Georgecaac5422014-03-25 14:18:18 +0000164 // found user-defined __build_class__, return it
Damien Georgeaea532e2014-02-06 22:57:51 +0000165 return elem->value;
166 } else {
Damien Georgecaac5422014-03-25 14:18:18 +0000167 // no user-defined __build_class__, return builtin one
Damien Georgeaea532e2014-02-06 22:57:51 +0000168 return (mp_obj_t)&mp_builtin___build_class___obj;
Damien429d7192013-10-04 19:53:11 +0100169 }
Damien429d7192013-10-04 19:53:11 +0100170}
171
Damiend99b0522013-12-21 18:17:45 +0000172mp_obj_t rt_get_cell(mp_obj_t cell) {
173 return mp_obj_cell_get(cell);
Damien660365e2013-12-17 18:27:24 +0000174}
175
Damiend99b0522013-12-21 18:17:45 +0000176void rt_set_cell(mp_obj_t cell, mp_obj_t val) {
177 mp_obj_cell_set(cell, val);
Damien660365e2013-12-17 18:27:24 +0000178}
179
Damiend99b0522013-12-21 18:17:45 +0000180void rt_store_name(qstr qstr, mp_obj_t obj) {
Damiena3977762013-10-09 23:10:10 +0100181 DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qstr), obj);
Damien George38a2da62014-01-08 17:33:12 +0000182 mp_map_lookup(map_locals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = obj;
Damiena3977762013-10-09 23:10:10 +0100183}
184
Paul Sokolovskyf9090342014-03-23 21:19:02 +0200185void rt_delete_name(qstr qstr) {
186 DEBUG_OP_printf("delete name %s\n", qstr_str(qstr));
187 mp_map_lookup(map_locals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
188}
189
Damiend99b0522013-12-21 18:17:45 +0000190void rt_store_global(qstr qstr, mp_obj_t obj) {
Damiena3977762013-10-09 23:10:10 +0100191 DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qstr), obj);
Damien George38a2da62014-01-08 17:33:12 +0000192 mp_map_lookup(map_globals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = obj;
Damien429d7192013-10-04 19:53:11 +0100193}
194
Damiend99b0522013-12-21 18:17:45 +0000195mp_obj_t rt_unary_op(int op, mp_obj_t arg) {
Damien7410e442013-11-02 19:47:57 +0000196 DEBUG_OP_printf("unary %d %p\n", op, arg);
Damien George9aa2a522014-02-01 23:04:09 +0000197
Damiend99b0522013-12-21 18:17:45 +0000198 if (MP_OBJ_IS_SMALL_INT(arg)) {
199 mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(arg);
Damien7410e442013-11-02 19:47:57 +0000200 switch (op) {
Damien George9d68e9c2014-03-12 15:38:15 +0000201 case RT_UNARY_OP_BOOL:
202 return MP_BOOL(val != 0);
203 case RT_UNARY_OP_POSITIVE:
204 return arg;
205 case RT_UNARY_OP_NEGATIVE:
206 // check for overflow
207 if (val == MP_SMALL_INT_MIN) {
208 return mp_obj_new_int(-val);
209 } else {
210 return MP_OBJ_NEW_SMALL_INT(-val);
211 }
212 case RT_UNARY_OP_INVERT:
213 return MP_OBJ_NEW_SMALL_INT(~val);
214 default:
215 assert(0);
216 return arg;
Damien7410e442013-11-02 19:47:57 +0000217 }
Damien George1e708fe2014-01-23 18:27:51 +0000218 } else {
219 mp_obj_type_t *type = mp_obj_get_type(arg);
220 if (type->unary_op != NULL) {
221 mp_obj_t result = type->unary_op(op, arg);
Damiend99b0522013-12-21 18:17:45 +0000222 if (result != NULL) {
223 return result;
224 }
Damien7410e442013-11-02 19:47:57 +0000225 }
Damiend99b0522013-12-21 18:17:45 +0000226 // TODO specify in error message what the operator is
Damien George0ec6bd42014-03-09 16:29:36 +0000227 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "bad operand type for unary operator: '%s'", mp_obj_get_type_str(arg)));
Damien7410e442013-11-02 19:47:57 +0000228 }
Damien429d7192013-10-04 19:53:11 +0100229}
230
Damiend99b0522013-12-21 18:17:45 +0000231mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
Damien429d7192013-10-04 19:53:11 +0100232 DEBUG_OP_printf("binary %d %p %p\n", op, lhs, rhs);
Damien George14f945c2014-01-03 14:09:31 +0000233
234 // TODO correctly distinguish inplace operators for mutable objects
235 // lookup logic that CPython uses for +=:
236 // check for implemented +=
237 // then check for implemented +
238 // then check for implemented seq.inplace_concat
239 // then check for implemented seq.concat
240 // then fail
241 // note that list does not implement + or +=, so that inplace_concat is reached first for +=
242
Damien George9aa2a522014-02-01 23:04:09 +0000243 // deal with is
244 if (op == RT_BINARY_OP_IS) {
Paul Sokolovsky8bc96472014-01-15 00:31:28 +0200245 return MP_BOOL(lhs == rhs);
246 }
Paul Sokolovsky8bc96472014-01-15 00:31:28 +0200247
Damien Georgebcbeea02014-01-11 10:47:22 +0000248 // deal with == and != for all types
Damien George9aa2a522014-02-01 23:04:09 +0000249 if (op == RT_BINARY_OP_EQUAL || op == RT_BINARY_OP_NOT_EQUAL) {
Damien Georgebcbeea02014-01-11 10:47:22 +0000250 if (mp_obj_equal(lhs, rhs)) {
Damien George9aa2a522014-02-01 23:04:09 +0000251 if (op == RT_BINARY_OP_EQUAL) {
Damien Georgebcbeea02014-01-11 10:47:22 +0000252 return mp_const_true;
253 } else {
254 return mp_const_false;
255 }
256 } else {
Damien George9aa2a522014-02-01 23:04:09 +0000257 if (op == RT_BINARY_OP_EQUAL) {
Damien Georgebcbeea02014-01-11 10:47:22 +0000258 return mp_const_false;
259 } else {
260 return mp_const_true;
261 }
262 }
263 }
264
265 // deal with exception_match for all types
Damien George9aa2a522014-02-01 23:04:09 +0000266 if (op == RT_BINARY_OP_EXCEPTION_MATCH) {
Damien Georgec5966122014-02-15 16:10:44 +0000267 // rhs must be issubclass(rhs, BaseException)
268 if (mp_obj_is_exception_type(rhs)) {
269 // if lhs is an instance of an exception, then extract and use its type
270 if (mp_obj_is_exception_instance(lhs)) {
271 lhs = mp_obj_get_type(lhs);
272 }
Damien George71510152014-03-03 22:38:13 +0000273 if (mp_obj_is_subclass_fast(lhs, rhs)) {
Damien Georgebcbeea02014-01-11 10:47:22 +0000274 return mp_const_true;
275 } else {
276 return mp_const_false;
277 }
278 }
Paul Sokolovsky4b2b7ce2014-03-23 20:49:39 +0200279 assert(0);
280 return mp_const_false;
Damien Georgebcbeea02014-01-11 10:47:22 +0000281 }
282
Damien George1a9951d2014-01-06 22:13:00 +0000283 if (MP_OBJ_IS_SMALL_INT(lhs)) {
Damiend99b0522013-12-21 18:17:45 +0000284 mp_small_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs);
Damien George1a9951d2014-01-06 22:13:00 +0000285 if (MP_OBJ_IS_SMALL_INT(rhs)) {
286 mp_small_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs);
Damien George9d68e9c2014-03-12 15:38:15 +0000287 // This is a binary operation: lhs_val op rhs_val
288 // We need to be careful to handle overflow; see CERT INT32-C
289 // Operations that can overflow:
290 // + result always fits in machine_int_t, then handled by SMALL_INT check
291 // - result always fits in machine_int_t, then handled by SMALL_INT check
292 // * checked explicitly
293 // / if lhs=MIN and rhs=-1; result always fits in machine_int_t, then handled by SMALL_INT check
294 // % if lhs=MIN and rhs=-1; result always fits in machine_int_t, then handled by SMALL_INT check
295 // << checked explicitly
Damien George1a9951d2014-01-06 22:13:00 +0000296 switch (op) {
297 case RT_BINARY_OP_OR:
298 case RT_BINARY_OP_INPLACE_OR: lhs_val |= rhs_val; break;
299 case RT_BINARY_OP_XOR:
300 case RT_BINARY_OP_INPLACE_XOR: lhs_val ^= rhs_val; break;
301 case RT_BINARY_OP_AND:
302 case RT_BINARY_OP_INPLACE_AND: lhs_val &= rhs_val; break;
303 case RT_BINARY_OP_LSHIFT:
Damien George9d68e9c2014-03-12 15:38:15 +0000304 case RT_BINARY_OP_INPLACE_LSHIFT: {
305 if (rhs_val < 0) {
306 // negative shift not allowed
307 nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
308 } else if (rhs_val >= BITS_PER_WORD || lhs_val > (MP_SMALL_INT_MAX >> rhs_val) || lhs_val < (MP_SMALL_INT_MIN >> rhs_val)) {
309 // left-shift will overflow, so use higher precision integer
310 lhs = mp_obj_new_int_from_ll(lhs_val);
311 goto generic_binary_op;
312 } else {
313 // use standard precision
314 lhs_val <<= rhs_val;
315 }
316 break;
317 }
Damien George1a9951d2014-01-06 22:13:00 +0000318 case RT_BINARY_OP_RSHIFT:
Damien George9d68e9c2014-03-12 15:38:15 +0000319 case RT_BINARY_OP_INPLACE_RSHIFT:
320 if (rhs_val < 0) {
321 // negative shift not allowed
322 nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
323 } else {
324 // standard precision is enough for right-shift
325 lhs_val >>= rhs_val;
326 }
327 break;
Damien George1a9951d2014-01-06 22:13:00 +0000328 case RT_BINARY_OP_ADD:
329 case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
330 case RT_BINARY_OP_SUBTRACT:
331 case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
332 case RT_BINARY_OP_MULTIPLY:
Damien George9d68e9c2014-03-12 15:38:15 +0000333 case RT_BINARY_OP_INPLACE_MULTIPLY: {
334
335 // If long long type exists and is larger than machine_int_t, then
336 // we can use the following code to perform overflow-checked multiplication.
337 // Otherwise (eg in x64 case) we must use the branching code below.
338 #if 0
339 // compute result using long long precision
340 long long res = (long long)lhs_val * (long long)rhs_val;
341 if (res > MP_SMALL_INT_MAX || res < MP_SMALL_INT_MIN) {
342 // result overflowed SMALL_INT, so return higher precision integer
343 return mp_obj_new_int_from_ll(res);
344 } else {
345 // use standard precision
346 lhs_val = (mp_small_int_t)res;
347 }
348 #endif
349
350 if (lhs_val > 0) { // lhs_val is positive
351 if (rhs_val > 0) { // lhs_val and rhs_val are positive
352 if (lhs_val > (MP_SMALL_INT_MAX / rhs_val)) {
353 goto mul_overflow;
354 }
355 } else { // lhs_val positive, rhs_val nonpositive
356 if (rhs_val < (MP_SMALL_INT_MIN / lhs_val)) {
357 goto mul_overflow;
358 }
359 } // lhs_val positive, rhs_val nonpositive
360 } else { // lhs_val is nonpositive
361 if (rhs_val > 0) { // lhs_val is nonpositive, rhs_val is positive
362 if (lhs_val < (MP_SMALL_INT_MIN / rhs_val)) {
363 goto mul_overflow;
364 }
365 } else { // lhs_val and rhs_val are nonpositive
366 if (lhs_val != 0 && rhs_val < (MP_SMALL_INT_MAX / lhs_val)) {
367 goto mul_overflow;
368 }
369 } // End if lhs_val and rhs_val are nonpositive
370 } // End if lhs_val is nonpositive
371
372 // use standard precision
373 return MP_OBJ_NEW_SMALL_INT(lhs_val * rhs_val);
374
375 mul_overflow:
376 // use higher precision
377 lhs = mp_obj_new_int_from_ll(lhs_val);
378 goto generic_binary_op;
379
380 break;
381 }
Damien George1a9951d2014-01-06 22:13:00 +0000382 case RT_BINARY_OP_FLOOR_DIVIDE:
Rachel Dowdall56402792014-03-22 20:19:24 +0000383 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE:
384 {
385 lhs_val = python_floor_divide(lhs_val, rhs_val);
386 break;
387 }
Damien George9d68e9c2014-03-12 15:38:15 +0000388 #if MICROPY_ENABLE_FLOAT
Damien George1a9951d2014-01-06 22:13:00 +0000389 case RT_BINARY_OP_TRUE_DIVIDE:
390 case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val);
Damien George9d68e9c2014-03-12 15:38:15 +0000391 #endif
Damiena3dcd9e2013-12-17 21:35:38 +0000392
Damien George1a9951d2014-01-06 22:13:00 +0000393 case RT_BINARY_OP_MODULO:
Rachel Dowdallcde86312014-03-22 17:29:27 +0000394 case RT_BINARY_OP_INPLACE_MODULO:
395 {
396 lhs_val = python_modulo(lhs_val, rhs_val);
397 break;
398 }
Damien George1a9951d2014-01-06 22:13:00 +0000399 case RT_BINARY_OP_POWER:
400 case RT_BINARY_OP_INPLACE_POWER:
Damien George9d68e9c2014-03-12 15:38:15 +0000401 if (rhs_val < 0) {
402 #if MICROPY_ENABLE_FLOAT
403 lhs = mp_obj_new_float(lhs_val);
404 goto generic_binary_op;
405 #else
406 nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "negative power with no float support"));
407 #endif
408 } else {
409 // TODO check for overflow
410 machine_int_t ans = 1;
411 while (rhs_val > 0) {
412 if (rhs_val & 1) {
413 ans *= lhs_val;
414 }
415 lhs_val *= lhs_val;
416 rhs_val /= 2;
Damien George1a9951d2014-01-06 22:13:00 +0000417 }
Damien George9d68e9c2014-03-12 15:38:15 +0000418 lhs_val = ans;
Damiena3dcd9e2013-12-17 21:35:38 +0000419 }
Damien George1a9951d2014-01-06 22:13:00 +0000420 break;
Damien George9aa2a522014-02-01 23:04:09 +0000421 case RT_BINARY_OP_LESS: return MP_BOOL(lhs_val < rhs_val); break;
422 case RT_BINARY_OP_MORE: return MP_BOOL(lhs_val > rhs_val); break;
423 case RT_BINARY_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val); break;
424 case RT_BINARY_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val); break;
Damiena3dcd9e2013-12-17 21:35:38 +0000425
Damien George1a9951d2014-01-06 22:13:00 +0000426 default: assert(0);
427 }
Paul Sokolovsky757ac812014-01-12 17:06:25 +0200428 // TODO: We just should make mp_obj_new_int() inline and use that
429 if (MP_OBJ_FITS_SMALL_INT(lhs_val)) {
Damien George1a9951d2014-01-06 22:13:00 +0000430 return MP_OBJ_NEW_SMALL_INT(lhs_val);
Damien George9d68e9c2014-03-12 15:38:15 +0000431 } else {
432 return mp_obj_new_int(lhs_val);
Damien George1a9951d2014-01-06 22:13:00 +0000433 }
Damien George3f759b72014-01-31 00:42:12 +0000434#if MICROPY_ENABLE_FLOAT
Damien George0c36da02014-03-08 15:24:39 +0000435 } else if (MP_OBJ_IS_TYPE(rhs, &mp_type_float)) {
Damien George1a9951d2014-01-06 22:13:00 +0000436 return mp_obj_float_binary_op(op, lhs_val, rhs);
Damien George0c36da02014-03-08 15:24:39 +0000437 } else if (MP_OBJ_IS_TYPE(rhs, &mp_type_complex)) {
Damien George1a9951d2014-01-06 22:13:00 +0000438 return mp_obj_complex_binary_op(op, lhs_val, 0, rhs);
Damien George3f759b72014-01-31 00:42:12 +0000439#endif
Damien429d7192013-10-04 19:53:11 +0100440 }
John R. Lentonc1bef212014-01-11 12:39:33 +0000441 }
John R. Lentonb8698fc2014-01-11 00:58:59 +0000442
Damien George9aa2a522014-02-01 23:04:09 +0000443 /* deal with `in`
John R. Lentonc1bef212014-01-11 12:39:33 +0000444 *
445 * NOTE `a in b` is `b.__contains__(a)`, hence why the generic dispatch
Damien George48697f12014-02-01 23:32:29 +0000446 * needs to go below with swapped arguments
John R. Lentonc1bef212014-01-11 12:39:33 +0000447 */
Damien George9aa2a522014-02-01 23:04:09 +0000448 if (op == RT_BINARY_OP_IN) {
Damien George5fa93b62014-01-22 14:35:10 +0000449 mp_obj_type_t *type = mp_obj_get_type(rhs);
450 if (type->binary_op != NULL) {
451 mp_obj_t res = type->binary_op(op, rhs, lhs);
Damien George48697f12014-02-01 23:32:29 +0000452 if (res != MP_OBJ_NULL) {
Damien George5fa93b62014-01-22 14:35:10 +0000453 return res;
454 }
455 }
456 if (type->getiter != NULL) {
457 /* second attempt, walk the iterator */
458 mp_obj_t next = NULL;
459 mp_obj_t iter = rt_getiter(rhs);
Damien George66eaf842014-03-26 19:27:58 +0000460 while ((next = rt_iternext(iter)) != MP_OBJ_NULL) {
Damien George5fa93b62014-01-22 14:35:10 +0000461 if (mp_obj_equal(next, lhs)) {
Damien George9aa2a522014-02-01 23:04:09 +0000462 return mp_const_true;
John R. Lentonb8698fc2014-01-11 00:58:59 +0000463 }
Damien7410e442013-11-02 19:47:57 +0000464 }
Damien George9aa2a522014-02-01 23:04:09 +0000465 return mp_const_false;
Damien7410e442013-11-02 19:47:57 +0000466 }
John R. Lentonc1bef212014-01-11 12:39:33 +0000467
468 nlr_jump(mp_obj_new_exception_msg_varg(
Damien Georgec5966122014-02-15 16:10:44 +0000469 &mp_type_TypeError, "'%s' object is not iterable",
John R. Lentonc1bef212014-01-11 12:39:33 +0000470 mp_obj_get_type_str(rhs)));
471 return mp_const_none;
472 }
473
Damien George5fa93b62014-01-22 14:35:10 +0000474 // generic binary_op supplied by type
Damien George9d68e9c2014-03-12 15:38:15 +0000475 mp_obj_type_t *type;
476generic_binary_op:
477 type = mp_obj_get_type(lhs);
Damien George5fa93b62014-01-22 14:35:10 +0000478 if (type->binary_op != NULL) {
479 mp_obj_t result = type->binary_op(op, lhs, rhs);
480 if (result != MP_OBJ_NULL) {
481 return result;
John R. Lentonc1bef212014-01-11 12:39:33 +0000482 }
Damien429d7192013-10-04 19:53:11 +0100483 }
Damiend99b0522013-12-21 18:17:45 +0000484
Damien George5fa93b62014-01-22 14:35:10 +0000485 // TODO implement dispatch for reverse binary ops
486
Damiend99b0522013-12-21 18:17:45 +0000487 // TODO specify in error message what the operator is
Damien Georgec5966122014-02-15 16:10:44 +0000488 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
Paul Sokolovskybab5cfb2014-01-10 17:32:22 +0200489 "unsupported operand types for binary operator: '%s', '%s'",
490 mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs)));
John R. Lentonc1bef212014-01-11 12:39:33 +0000491 return mp_const_none;
Damien429d7192013-10-04 19:53:11 +0100492}
493
Damiend99b0522013-12-21 18:17:45 +0000494mp_obj_t rt_call_function_0(mp_obj_t fun) {
Damien George20006db2014-01-18 14:10:48 +0000495 return rt_call_function_n_kw(fun, 0, 0, NULL);
Damieneb19efb2013-10-10 22:06:54 +0100496}
497
Damiend99b0522013-12-21 18:17:45 +0000498mp_obj_t rt_call_function_1(mp_obj_t fun, mp_obj_t arg) {
Damien George20006db2014-01-18 14:10:48 +0000499 return rt_call_function_n_kw(fun, 1, 0, &arg);
Damieneb19efb2013-10-10 22:06:54 +0100500}
501
Damiend99b0522013-12-21 18:17:45 +0000502mp_obj_t rt_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) {
503 mp_obj_t args[2];
Damien George20006db2014-01-18 14:10:48 +0000504 args[0] = arg1;
505 args[1] = arg2;
506 return rt_call_function_n_kw(fun, 2, 0, args);
Damieneb19efb2013-10-10 22:06:54 +0100507}
508
Damien Georgecd82e022014-02-02 13:11:48 +0000509// wrapper that accepts n_args and n_kw in one argument
510// native emitter can only pass at most 3 arguments to a function
511mp_obj_t rt_call_function_n_kw_for_native(mp_obj_t fun_in, uint n_args_kw, const mp_obj_t *args) {
512 return rt_call_function_n_kw(fun_in, n_args_kw & 0xff, (n_args_kw >> 8) & 0xff, args);
513}
514
Damien George20006db2014-01-18 14:10:48 +0000515// args contains, eg: arg0 arg1 key0 value0 key1 value1
516mp_obj_t rt_call_function_n_kw(mp_obj_t fun_in, uint n_args, uint n_kw, const mp_obj_t *args) {
Damiend99b0522013-12-21 18:17:45 +0000517 // TODO improve this: fun object can specify its type and we parse here the arguments,
518 // passing to the function arrays of fixed and keyword arguments
Damieneb19efb2013-10-10 22:06:54 +0100519
John R. Lenton9c83ec02014-01-07 23:06:46 +0000520 DEBUG_OP_printf("calling function %p(n_args=%d, n_kw=%d, args=%p)\n", fun_in, n_args, n_kw, args);
521
Damien George8b56beb2014-01-31 23:49:49 +0000522 // get the type
523 mp_obj_type_t *type = mp_obj_get_type(fun_in);
524
525 // do the call
526 if (type->call != NULL) {
527 return type->call(fun_in, n_args, n_kw, args);
John R. Lenton9c83ec02014-01-07 23:06:46 +0000528 } else {
Damien George0ec6bd42014-03-09 16:29:36 +0000529 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not callable", mp_obj_get_type_str(fun_in)));
John R. Lenton9c83ec02014-01-07 23:06:46 +0000530 }
Damien86c7fc72013-11-26 15:16:41 +0000531}
532
Damien George20006db2014-01-18 14:10:48 +0000533// args contains: fun self/NULL arg(0) ... arg(n_args-2) arg(n_args-1) kw_key(0) kw_val(0) ... kw_key(n_kw-1) kw_val(n_kw-1)
534// if n_args==0 and n_kw==0 then there are only fun and self/NULL
Damiend99b0522013-12-21 18:17:45 +0000535mp_obj_t rt_call_method_n_kw(uint n_args, uint n_kw, const mp_obj_t *args) {
Damien George20006db2014-01-18 14:10:48 +0000536 DEBUG_OP_printf("call method (fun=%p, self=%p, n_args=%u, n_kw=%u, args=%p)\n", args[0], args[1], n_args, n_kw, args);
537 int adjust = (args[1] == NULL) ? 0 : 1;
538 return rt_call_function_n_kw(args[0], n_args + adjust, n_kw, args + 2 - adjust);
Damien86c7fc72013-11-26 15:16:41 +0000539}
540
Damiend99b0522013-12-21 18:17:45 +0000541mp_obj_t rt_build_tuple(int n_args, mp_obj_t *items) {
Damien George20006db2014-01-18 14:10:48 +0000542 return mp_obj_new_tuple(n_args, items);
Damienc226dca2013-10-16 16:12:52 +0100543}
544
Damiend99b0522013-12-21 18:17:45 +0000545mp_obj_t rt_build_list(int n_args, mp_obj_t *items) {
Damien George20006db2014-01-18 14:10:48 +0000546 return mp_obj_new_list(n_args, items);
Damien429d7192013-10-04 19:53:11 +0100547}
548
Damiend99b0522013-12-21 18:17:45 +0000549mp_obj_t rt_build_set(int n_args, mp_obj_t *items) {
550 return mp_obj_new_set(n_args, items);
Damien429d7192013-10-04 19:53:11 +0100551}
552
Damiend99b0522013-12-21 18:17:45 +0000553mp_obj_t rt_store_set(mp_obj_t set, mp_obj_t item) {
Damiendae7eb72013-12-29 22:32:51 +0000554 mp_obj_set_store(set, item);
Damienc12aa462013-10-16 20:57:49 +0100555 return set;
556}
557
Damien George932bf1c2014-01-18 23:42:49 +0000558// unpacked items are stored in reverse order into the array pointed to by items
Damiend99b0522013-12-21 18:17:45 +0000559void rt_unpack_sequence(mp_obj_t seq_in, uint num, mp_obj_t *items) {
Paul Sokolovskyedbdf712014-02-02 00:54:06 +0200560 uint seq_len;
Damien George3e1a5c12014-03-29 13:43:38 +0000561 if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {
Damiend99b0522013-12-21 18:17:45 +0000562 mp_obj_t *seq_items;
Damien George07ddab52014-03-29 13:15:08 +0000563 if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple)) {
Damiend99b0522013-12-21 18:17:45 +0000564 mp_obj_tuple_get(seq_in, &seq_len, &seq_items);
565 } else {
566 mp_obj_list_get(seq_in, &seq_len, &seq_items);
Damien86c7fc72013-11-26 15:16:41 +0000567 }
Damiend99b0522013-12-21 18:17:45 +0000568 if (seq_len < num) {
Paul Sokolovskyedbdf712014-02-02 00:54:06 +0200569 goto too_short;
Damiend99b0522013-12-21 18:17:45 +0000570 } else if (seq_len > num) {
Paul Sokolovskyedbdf712014-02-02 00:54:06 +0200571 goto too_long;
Damiend99b0522013-12-21 18:17:45 +0000572 }
Damien George932bf1c2014-01-18 23:42:49 +0000573 for (uint i = 0; i < num; i++) {
574 items[i] = seq_items[num - 1 - i];
575 }
Damien86c7fc72013-11-26 15:16:41 +0000576 } else {
Paul Sokolovskyedbdf712014-02-02 00:54:06 +0200577 mp_obj_t iterable = rt_getiter(seq_in);
578
579 for (seq_len = 0; seq_len < num; seq_len++) {
580 mp_obj_t el = rt_iternext(iterable);
Damien George66eaf842014-03-26 19:27:58 +0000581 if (el == MP_OBJ_NULL) {
Paul Sokolovskyedbdf712014-02-02 00:54:06 +0200582 goto too_short;
583 }
584 items[num - 1 - seq_len] = el;
585 }
Damien George66eaf842014-03-26 19:27:58 +0000586 if (rt_iternext(iterable) != MP_OBJ_NULL) {
Paul Sokolovskyedbdf712014-02-02 00:54:06 +0200587 goto too_long;
588 }
Damien86c7fc72013-11-26 15:16:41 +0000589 }
Paul Sokolovskyedbdf712014-02-02 00:54:06 +0200590 return;
591
592too_short:
Damien Georgec5966122014-02-15 16:10:44 +0000593 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "need more than %d values to unpack", seq_len));
Paul Sokolovskyedbdf712014-02-02 00:54:06 +0200594too_long:
Damien Georgec5966122014-02-15 16:10:44 +0000595 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "too many values to unpack (expected %d)", num));
Damien86c7fc72013-11-26 15:16:41 +0000596}
597
Damiend99b0522013-12-21 18:17:45 +0000598mp_obj_t rt_build_map(int n_args) {
599 return mp_obj_new_dict(n_args);
Damien429d7192013-10-04 19:53:11 +0100600}
601
Damiend99b0522013-12-21 18:17:45 +0000602mp_obj_t rt_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value) {
603 // map should always be a dict
604 return mp_obj_dict_store(map, key, value);
Damien429d7192013-10-04 19:53:11 +0100605}
606
Damiend99b0522013-12-21 18:17:45 +0000607mp_obj_t rt_load_attr(mp_obj_t base, qstr attr) {
Damien George062478e2014-01-09 20:57:50 +0000608 DEBUG_OP_printf("load attr %p.%s\n", base, qstr_str(attr));
609 // use load_method
610 mp_obj_t dest[2];
611 rt_load_method(base, attr, dest);
Damien George7c9c6672014-01-25 00:17:36 +0000612 if (dest[1] == MP_OBJ_NULL) {
Damien George062478e2014-01-09 20:57:50 +0000613 // load_method returned just a normal attribute
Damien George20006db2014-01-18 14:10:48 +0000614 return dest[0];
Damien George062478e2014-01-09 20:57:50 +0000615 } else {
616 // load_method returned a method, so build a bound method object
617 return mp_obj_new_bound_meth(dest[0], dest[1]);
Damiend99b0522013-12-21 18:17:45 +0000618 }
Damiend99b0522013-12-21 18:17:45 +0000619}
620
Damien George7c9c6672014-01-25 00:17:36 +0000621// no attribute found, returns: dest[0] == MP_OBJ_NULL, dest[1] == MP_OBJ_NULL
622// normal attribute found, returns: dest[0] == <attribute>, dest[1] == MP_OBJ_NULL
623// method attribute found, returns: dest[0] == <method>, dest[1] == <self>
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200624STATIC void rt_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest) {
Damien George062478e2014-01-09 20:57:50 +0000625 // clear output to indicate no attribute/method found yet
626 dest[0] = MP_OBJ_NULL;
627 dest[1] = MP_OBJ_NULL;
628
629 // get the type
630 mp_obj_type_t *type = mp_obj_get_type(base);
631
632 // if this type can do its own load, then call it
633 if (type->load_attr != NULL) {
634 type->load_attr(base, attr, dest);
635 }
636
637 // if nothing found yet, look for built-in and generic names
Damien George7c9c6672014-01-25 00:17:36 +0000638 if (dest[0] == MP_OBJ_NULL) {
Damien George35e2a4e2014-02-05 00:51:47 +0000639 if (attr == MP_QSTR___class__) {
640 // a.__class__ is equivalent to type(a)
641 dest[0] = type;
642 } else if (attr == MP_QSTR___next__ && type->iternext != NULL) {
Damien George20006db2014-01-18 14:10:48 +0000643 dest[0] = (mp_obj_t)&mp_builtin_next_obj;
644 dest[1] = base;
Damien Georgef49ba1b2014-01-18 17:52:41 +0000645 } else if (type->load_attr == NULL) {
646 // generic method lookup if type didn't provide a specific one
Damien Georgeeae16442014-01-11 19:22:29 +0000647 // this is a lookup in the object (ie not class or type)
Damien George9b196cd2014-03-26 21:47:19 +0000648 if (type->locals_dict != NULL) {
Damien George3e1a5c12014-03-29 13:43:38 +0000649 assert(MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)); // Micro Python restriction, for now
Damien George9b196cd2014-03-26 21:47:19 +0000650 mp_map_t *locals_map = mp_obj_dict_get_map(type->locals_dict);
651 mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
652 if (elem != NULL) {
653 // check if the methods are functions, static or class methods
654 // see http://docs.python.org/3.3/howto/descriptor.html
655 if (MP_OBJ_IS_TYPE(elem->value, &mp_type_staticmethod)) {
656 // return just the function
657 dest[0] = ((mp_obj_static_class_method_t*)elem->value)->fun;
658 } else if (MP_OBJ_IS_TYPE(elem->value, &mp_type_classmethod)) {
659 // return a bound method, with self being the type of this object
660 dest[0] = ((mp_obj_static_class_method_t*)elem->value)->fun;
661 dest[1] = mp_obj_get_type(base);
Damien Georgec3f11262014-03-26 22:35:10 +0000662 } else if (mp_obj_is_callable(elem->value)) {
Damien George9b196cd2014-03-26 21:47:19 +0000663 // return a bound method, with self being this object
Damien Georgec3f11262014-03-26 22:35:10 +0000664 dest[0] = elem->value;
Damien George9b196cd2014-03-26 21:47:19 +0000665 dest[1] = base;
Damien Georgec3f11262014-03-26 22:35:10 +0000666 } else {
667 // class member is a value, so just return that value
668 dest[0] = elem->value;
Damien George062478e2014-01-09 20:57:50 +0000669 }
John R. Lenton9c83ec02014-01-07 23:06:46 +0000670 }
Damiend57eba52013-11-02 23:58:14 +0000671 }
672 }
Damiena3977762013-10-09 23:10:10 +0100673 }
Damien George7c9c6672014-01-25 00:17:36 +0000674}
Damiena3977762013-10-09 23:10:10 +0100675
Damien George7c9c6672014-01-25 00:17:36 +0000676void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) {
677 DEBUG_OP_printf("load method %p.%s\n", base, qstr_str(attr));
678
679 rt_load_method_maybe(base, attr, dest);
680
681 if (dest[0] == MP_OBJ_NULL) {
Damien George062478e2014-01-09 20:57:50 +0000682 // no attribute/method called attr
683 // following CPython, we give a more detailed error message for type objects
Damien Georgec5966122014-02-15 16:10:44 +0000684 if (MP_OBJ_IS_TYPE(base, &mp_type_type)) {
Paul Sokolovsky7f8b3132014-03-25 00:55:39 +0200685 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_AttributeError,
686 "type object '%s' has no attribute '%s'", qstr_str(((mp_obj_type_t*)base)->name), qstr_str(attr)));
Damien George062478e2014-01-09 20:57:50 +0000687 } else {
Damien Georgec5966122014-02-15 16:10:44 +0000688 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
Damien George062478e2014-01-09 20:57:50 +0000689 }
690 }
Damiena3977762013-10-09 23:10:10 +0100691}
692
Damiend99b0522013-12-21 18:17:45 +0000693void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) {
Damien5ac1b2e2013-10-18 19:58:12 +0100694 DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value);
Damien George062478e2014-01-09 20:57:50 +0000695 mp_obj_type_t *type = mp_obj_get_type(base);
696 if (type->store_attr != NULL) {
697 if (type->store_attr(base, attr, value)) {
698 return;
699 }
Damiena3977762013-10-09 23:10:10 +0100700 }
Damien Georgec5966122014-02-15 16:10:44 +0000701 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
Damiena3977762013-10-09 23:10:10 +0100702}
703
Damiend99b0522013-12-21 18:17:45 +0000704void rt_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) {
Damien5ac1b2e2013-10-18 19:58:12 +0100705 DEBUG_OP_printf("store subscr %p[%p] <- %p\n", base, index, value);
Damien George3e1a5c12014-03-29 13:43:38 +0000706 if (MP_OBJ_IS_TYPE(base, &mp_type_list)) {
Damien429d7192013-10-04 19:53:11 +0100707 // list store
Damiend99b0522013-12-21 18:17:45 +0000708 mp_obj_list_store(base, index, value);
Damien George3e1a5c12014-03-29 13:43:38 +0000709 } else if (MP_OBJ_IS_TYPE(base, &mp_type_dict)) {
Damiend99b0522013-12-21 18:17:45 +0000710 // dict store
711 mp_obj_dict_store(base, index, value);
Damien429d7192013-10-04 19:53:11 +0100712 } else {
Paul Sokolovsky6d8edf62014-01-18 13:10:51 +0200713 mp_obj_type_t *type = mp_obj_get_type(base);
714 if (type->store_item != NULL) {
715 bool r = type->store_item(base, index, value);
716 if (r) {
717 return;
718 }
719 // TODO: call base classes here?
720 }
Damien Georgec5966122014-02-15 16:10:44 +0000721 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item assignment", mp_obj_get_type_str(base)));
Damien429d7192013-10-04 19:53:11 +0100722 }
723}
724
Damiend99b0522013-12-21 18:17:45 +0000725mp_obj_t rt_getiter(mp_obj_t o_in) {
Damien George5fa93b62014-01-22 14:35:10 +0000726 mp_obj_type_t *type = mp_obj_get_type(o_in);
727 if (type->getiter != NULL) {
728 return type->getiter(o_in);
Damience89a212013-10-15 22:25:17 +0100729 } else {
Damien George9e6e9352014-03-26 18:37:06 +0000730 // check for __iter__ method
Damien George7c9c6672014-01-25 00:17:36 +0000731 mp_obj_t dest[2];
Damien George9e6e9352014-03-26 18:37:06 +0000732 rt_load_method_maybe(o_in, MP_QSTR___iter__, dest);
Damien George7c9c6672014-01-25 00:17:36 +0000733 if (dest[0] != MP_OBJ_NULL) {
Damien George9e6e9352014-03-26 18:37:06 +0000734 // __iter__ exists, call it and return its result
735 return rt_call_method_n_kw(0, 0, dest);
Damien George7c9c6672014-01-25 00:17:36 +0000736 } else {
Damien George9e6e9352014-03-26 18:37:06 +0000737 rt_load_method_maybe(o_in, MP_QSTR___getitem__, dest);
738 if (dest[0] != MP_OBJ_NULL) {
739 // __getitem__ exists, create an iterator
740 return mp_obj_new_getitem_iter(dest);
741 } else {
742 // object not iterable
743 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(o_in)));
744 }
Damien George7c9c6672014-01-25 00:17:36 +0000745 }
Damience89a212013-10-15 22:25:17 +0100746 }
747}
748
Damien George66eaf842014-03-26 19:27:58 +0000749// may return MP_OBJ_NULL as an optimisation instead of raise StopIteration()
750// may also raise StopIteration()
751mp_obj_t rt_iternext_allow_raise(mp_obj_t o_in) {
Damien George5fa93b62014-01-22 14:35:10 +0000752 mp_obj_type_t *type = mp_obj_get_type(o_in);
753 if (type->iternext != NULL) {
754 return type->iternext(o_in);
Damience89a212013-10-15 22:25:17 +0100755 } else {
Damien George9e6e9352014-03-26 18:37:06 +0000756 // check for __next__ method
757 mp_obj_t dest[2];
758 rt_load_method_maybe(o_in, MP_QSTR___next__, dest);
759 if (dest[0] != MP_OBJ_NULL) {
760 // __next__ exists, call it and return its result
761 return rt_call_method_n_kw(0, 0, dest);
762 } else {
763 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
764 }
Damien Georgec5966122014-02-15 16:10:44 +0000765 }
766}
767
Damien George66eaf842014-03-26 19:27:58 +0000768// will always return MP_OBJ_NULL instead of raising StopIteration() (or any subclass thereof)
769// may raise other exceptions
770mp_obj_t rt_iternext(mp_obj_t o_in) {
771 mp_obj_type_t *type = mp_obj_get_type(o_in);
772 if (type->iternext != NULL) {
773 return type->iternext(o_in);
774 } else {
775 // check for __next__ method
776 mp_obj_t dest[2];
777 rt_load_method_maybe(o_in, MP_QSTR___next__, dest);
778 if (dest[0] != MP_OBJ_NULL) {
779 // __next__ exists, call it and return its result
780 nlr_buf_t nlr;
781 if (nlr_push(&nlr) == 0) {
782 mp_obj_t ret = rt_call_method_n_kw(0, 0, dest);
783 nlr_pop();
784 return ret;
785 } else {
786 if (mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) {
787 return MP_OBJ_NULL;
788 } else {
789 nlr_jump(nlr.ret_val);
790 }
791 }
792 } else {
793 nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
794 }
795 }
796}
797
Damien Georgec5966122014-02-15 16:10:44 +0000798mp_obj_t rt_make_raise_obj(mp_obj_t o) {
799 DEBUG_printf("raise %p\n", o);
800 if (mp_obj_is_exception_type(o)) {
801 // o is an exception type (it is derived from BaseException (or is BaseException))
802 // create and return a new exception instance by calling o
Damien George22a08652014-02-15 21:05:25 +0000803 // TODO could have an option to disable traceback, then builtin exceptions (eg TypeError)
804 // could have const instances in ROM which we return here instead
Damien Georgec5966122014-02-15 16:10:44 +0000805 return rt_call_function_n_kw(o, 0, 0, NULL);
806 } else if (mp_obj_is_exception_instance(o)) {
807 // o is an instance of an exception, so use it as the exception
808 return o;
809 } else {
810 // o cannot be used as an exception, so return a type error (which will be raised by the caller)
811 return mp_obj_new_exception_msg(&mp_type_TypeError, "exceptions must derive from BaseException");
Damience89a212013-10-15 22:25:17 +0100812 }
813}
814
Damiend99b0522013-12-21 18:17:45 +0000815mp_obj_t rt_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) {
Damien George64131f32014-02-06 20:31:44 +0000816 DEBUG_printf("import name %s\n", qstr_str(name));
817
Damiendb4c3612013-12-10 17:27:24 +0000818 // build args array
Damiend99b0522013-12-21 18:17:45 +0000819 mp_obj_t args[5];
Damien George5fa93b62014-01-22 14:35:10 +0000820 args[0] = MP_OBJ_NEW_QSTR(name);
Damiend99b0522013-12-21 18:17:45 +0000821 args[1] = mp_const_none; // TODO should be globals
822 args[2] = mp_const_none; // TODO should be locals
Damiendb4c3612013-12-10 17:27:24 +0000823 args[3] = fromlist;
824 args[4] = level; // must be 0; we don't yet support other values
825
826 // TODO lookup __import__ and call that instead of going straight to builtin implementation
Damiend99b0522013-12-21 18:17:45 +0000827 return mp_builtin___import__(5, args);
Damiendb4c3612013-12-10 17:27:24 +0000828}
829
Damiend99b0522013-12-21 18:17:45 +0000830mp_obj_t rt_import_from(mp_obj_t module, qstr name) {
Damien George64131f32014-02-06 20:31:44 +0000831 DEBUG_printf("import from %p %s\n", module, qstr_str(name));
832
Damiend99b0522013-12-21 18:17:45 +0000833 mp_obj_t x = rt_load_attr(module, name);
Damiendb4c3612013-12-10 17:27:24 +0000834 /* TODO convert AttributeError to ImportError
835 if (fail) {
836 (ImportError, "cannot import name %s", qstr_str(name), NULL)
837 }
838 */
839 return x;
840}
841
Paul Sokolovskyda1ce932014-02-14 00:22:06 +0200842void rt_import_all(mp_obj_t module) {
843 DEBUG_printf("import all %p\n", module);
844
845 mp_map_t *map = mp_obj_module_get_globals(module);
846 for (uint i = 0; i < map->alloc; i++) {
847 if (map->table[i].key != MP_OBJ_NULL) {
848 rt_store_name(MP_OBJ_QSTR_VALUE(map->table[i].key), map->table[i].value);
849 }
850 }
851}
852
Damien George66028ab2014-01-03 14:03:48 +0000853mp_map_t *rt_locals_get(void) {
854 return map_locals;
855}
856
857void rt_locals_set(mp_map_t *m) {
858 DEBUG_OP_printf("rt_locals_set(%p)\n", m);
859 map_locals = m;
860}
861
862mp_map_t *rt_globals_get(void) {
863 return map_globals;
864}
865
866void rt_globals_set(mp_map_t *m) {
867 DEBUG_OP_printf("rt_globals_set(%p)\n", m);
868 map_globals = m;
869}
870
Damien6ba13142013-11-02 20:34:54 +0000871// these must correspond to the respective enum
Damiendf4b4f32013-10-19 18:28:01 +0100872void *const rt_fun_table[RT_F_NUMBER_OF] = {
Damien6ba13142013-11-02 20:34:54 +0000873 rt_load_const_dec,
Damien429d7192013-10-04 19:53:11 +0100874 rt_load_const_str,
875 rt_load_name,
876 rt_load_global,
Damien7f5dacf2013-10-10 11:24:39 +0100877 rt_load_build_class,
Damien429d7192013-10-04 19:53:11 +0100878 rt_load_attr,
879 rt_load_method,
880 rt_store_name,
Damien7f5dacf2013-10-10 11:24:39 +0100881 rt_store_attr,
Damien429d7192013-10-04 19:53:11 +0100882 rt_store_subscr,
883 rt_is_true,
884 rt_unary_op,
Damien Georgecd82e022014-02-02 13:11:48 +0000885 rt_binary_op,
Damiend2755ec2013-10-16 23:58:48 +0100886 rt_build_tuple,
Damien429d7192013-10-04 19:53:11 +0100887 rt_build_list,
Damiend2755ec2013-10-16 23:58:48 +0100888 rt_list_append,
Damien429d7192013-10-04 19:53:11 +0100889 rt_build_map,
890 rt_store_map,
891 rt_build_set,
Damiend2755ec2013-10-16 23:58:48 +0100892 rt_store_set,
Damien429d7192013-10-04 19:53:11 +0100893 rt_make_function_from_id,
Damien Georgecd82e022014-02-02 13:11:48 +0000894 rt_call_function_n_kw_for_native,
Damien George20006db2014-01-18 14:10:48 +0000895 rt_call_method_n_kw,
Damiend2755ec2013-10-16 23:58:48 +0100896 rt_getiter,
897 rt_iternext,
Damien429d7192013-10-04 19:53:11 +0100898};
899
900/*
901void rt_f_vector(rt_fun_kind_t fun_kind) {
902 (rt_f_table[fun_kind])();
903}
904*/