blob: 9da5688763809408c6bb762a4511f4f3392ea1e4 [file] [log] [blame]
Damienc226dca2013-10-16 16:12:52 +01001// in principle, rt_xxx functions are called only by vm/native/viper and make assumptions about args
2// py_xxx functions are safer and can be called by anyone
Damienbd254452013-10-16 20:39:12 +01003// note that rt_assign_xxx are called only from emit*, and maybe we can rename them to reflect this
Damienc226dca2013-10-16 16:12:52 +01004
Damien429d7192013-10-04 19:53:11 +01005#include <stdint.h>
6#include <stdlib.h>
7#include <stdio.h>
8#include <string.h>
9#include <assert.h>
10
Damience89a212013-10-15 22:25:17 +010011#include "nlr.h"
Damien429d7192013-10-04 19:53:11 +010012#include "misc.h"
Damienc025ebb2013-10-12 14:30:21 +010013#include "mpyconfig.h"
Damien429d7192013-10-04 19:53:11 +010014#include "runtime.h"
Damieneb19efb2013-10-10 22:06:54 +010015#include "bc.h"
Damien429d7192013-10-04 19:53:11 +010016
Damien7f5dacf2013-10-10 11:24:39 +010017#if 0 // print debugging info
Damiena1ddfcc2013-10-10 23:25:50 +010018#define DEBUG_PRINT (1)
19#define WRITE_NATIVE (1)
Damien7f5dacf2013-10-10 11:24:39 +010020#define DEBUG_printf(args...) printf(args)
21#define DEBUG_OP_printf(args...) printf(args)
22#else // don't print debugging info
Damiena3977762013-10-09 23:10:10 +010023#define DEBUG_printf(args...) (void)0
Damien429d7192013-10-04 19:53:11 +010024#define DEBUG_OP_printf(args...) (void)0
Damien7f5dacf2013-10-10 11:24:39 +010025#endif
Damien429d7192013-10-04 19:53:11 +010026
Damien429d7192013-10-04 19:53:11 +010027typedef machine_int_t py_small_int_t;
28
29#define IS_O(o, k) (((((py_small_int_t)(o)) & 1) == 0) && (((py_obj_base_t*)(o))->kind == (k)))
30#define IS_SMALL_INT(o) (((py_small_int_t)(o)) & 1)
31#define FROM_SMALL_INT(o) (((py_small_int_t)(o)) >> 1)
32#define TO_SMALL_INT(o) ((py_obj_t)(((o) << 1) | 1))
33
Damien3ef4abb2013-10-12 16:53:13 +010034#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +010035typedef machine_float_t float_t;
36#endif
37
38typedef enum {
39 O_CONST,
40 O_STR,
Damien3ef4abb2013-10-12 16:53:13 +010041#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +010042 O_FLOAT,
43#endif
Damience89a212013-10-15 22:25:17 +010044 O_EXCEPTION_0,
Damienf086ecf2013-10-22 16:05:11 +010045 O_EXCEPTION_N,
Damience89a212013-10-15 22:25:17 +010046 O_RANGE,
47 O_RANGE_IT,
Damien429d7192013-10-04 19:53:11 +010048 O_FUN_0,
49 O_FUN_1,
50 O_FUN_2,
51 O_FUN_N,
52 O_FUN_BC,
Damien826005c2013-10-05 23:17:28 +010053 O_FUN_ASM,
Damienbd254452013-10-16 20:39:12 +010054 O_GEN_WRAP,
55 O_GEN_INSTANCE,
Damien429d7192013-10-04 19:53:11 +010056 O_BOUND_METH,
Damienc226dca2013-10-16 16:12:52 +010057 O_TUPLE,
Damien429d7192013-10-04 19:53:11 +010058 O_LIST,
Damienc226dca2013-10-16 16:12:52 +010059 O_TUPLE_IT,
60 O_LIST_IT,
Damien429d7192013-10-04 19:53:11 +010061 O_SET,
62 O_MAP,
63 O_CLASS,
Damiena3977762013-10-09 23:10:10 +010064 O_OBJ,
Damien429d7192013-10-04 19:53:11 +010065} py_obj_kind_t;
66
67typedef enum {
68 MAP_QSTR,
69 MAP_PY_OBJ,
70} py_map_kind_t;
71
72typedef struct _py_map_elem_t {
73 py_obj_t key;
74 py_obj_t value;
75} py_map_elem_t;
76
77typedef struct _py_map_t {
Damienf086ecf2013-10-22 16:05:11 +010078 struct {
79 py_map_kind_t kind : 1;
80 machine_uint_t used : (8 * BYTES_PER_WORD - 1);
81 };
Damien429d7192013-10-04 19:53:11 +010082 machine_uint_t alloc;
Damien429d7192013-10-04 19:53:11 +010083 py_map_elem_t *table;
84} py_map_t;
85
Damiena3977762013-10-09 23:10:10 +010086typedef struct _py_obj_base_t py_obj_base_t;
87
88struct _py_obj_base_t {
Damien429d7192013-10-04 19:53:11 +010089 py_obj_kind_t kind;
90 union {
91 const char *id;
92 qstr u_str;
Damien3ef4abb2013-10-12 16:53:13 +010093#if MICROPY_ENABLE_FLOAT
Damiene4af64f2013-10-06 12:04:13 +010094 float_t u_flt;
Damien429d7192013-10-04 19:53:11 +010095#endif
Damience89a212013-10-15 22:25:17 +010096 struct { // for O_EXCEPTION_0
97 qstr id;
98 } u_exc0;
Damienf086ecf2013-10-22 16:05:11 +010099 struct { // for O_EXCEPTION_N
100 // TODO make generic object or something
Damience89a212013-10-15 22:25:17 +0100101 qstr id;
Damienf086ecf2013-10-22 16:05:11 +0100102 int n_args;
103 const void **args;
104 } u_exc_n;
Damience89a212013-10-15 22:25:17 +0100105 struct { // for O_RANGE
106 // TODO make generic object or something
107 machine_int_t start;
108 machine_int_t stop;
109 machine_int_t step;
110 } u_range;
111 struct { // for O_RANGE_IT
112 // TODO make generic object or something
113 machine_int_t cur;
114 machine_int_t stop;
115 machine_int_t step;
116 } u_range_it;
Damien429d7192013-10-04 19:53:11 +0100117 struct { // for O_FUN_[012N]
Damien429d7192013-10-04 19:53:11 +0100118 int n_args;
Damien826005c2013-10-05 23:17:28 +0100119 void *fun;
Damien429d7192013-10-04 19:53:11 +0100120 } u_fun;
121 struct { // for O_FUN_BC
Damien826005c2013-10-05 23:17:28 +0100122 int n_args;
Damien429d7192013-10-04 19:53:11 +0100123 byte *code;
124 uint len;
Damien429d7192013-10-04 19:53:11 +0100125 } u_fun_bc;
Damien826005c2013-10-05 23:17:28 +0100126 struct { // for O_FUN_ASM
127 int n_args;
128 void *fun;
129 } u_fun_asm;
Damienbd254452013-10-16 20:39:12 +0100130 struct { // for O_GEN_WRAP
131 int n_state;
132 py_obj_base_t *fun;
133 } u_gen_wrap;
134 struct { // for O_GEN_INSTANCE
135 py_obj_t *state;
136 const byte *ip;
137 py_obj_t *sp;
138 } u_gen_instance;
Damien429d7192013-10-04 19:53:11 +0100139 struct { // for O_BOUND_METH
140 py_obj_t meth;
141 py_obj_t self;
142 } u_bound_meth;
Damienc226dca2013-10-16 16:12:52 +0100143 struct { // for O_TUPLE, O_LIST
Damienf086ecf2013-10-22 16:05:11 +0100144 machine_uint_t alloc;
145 machine_uint_t len;
Damien429d7192013-10-04 19:53:11 +0100146 py_obj_t *items;
Damienc226dca2013-10-16 16:12:52 +0100147 } u_tuple_list;
148 struct { // for O_TUPLE_IT, O_LIST_IT
149 py_obj_base_t *obj;
Damienf086ecf2013-10-22 16:05:11 +0100150 machine_uint_t cur;
Damienc226dca2013-10-16 16:12:52 +0100151 } u_tuple_list_it;
Damien429d7192013-10-04 19:53:11 +0100152 struct { // for O_SET
Damienf086ecf2013-10-22 16:05:11 +0100153 machine_uint_t alloc;
154 machine_uint_t used;
Damien429d7192013-10-04 19:53:11 +0100155 py_obj_t *table;
156 } u_set;
157 py_map_t u_map; // for O_MAP
Damien429d7192013-10-04 19:53:11 +0100158 struct { // for O_CLASS
Damiena3977762013-10-09 23:10:10 +0100159 py_map_t *locals;
Damien429d7192013-10-04 19:53:11 +0100160 } u_class;
Damiena3977762013-10-09 23:10:10 +0100161 struct { // for O_OBJ
162 py_obj_base_t *class; // points to a O_CLASS object
163 py_map_t *members;
164 } u_obj;
Damien429d7192013-10-04 19:53:11 +0100165 };
Damiena3977762013-10-09 23:10:10 +0100166};
Damien429d7192013-10-04 19:53:11 +0100167
168py_obj_t py_const_none;
169py_obj_t py_const_false;
170py_obj_t py_const_true;
Damience89a212013-10-15 22:25:17 +0100171py_obj_t py_const_stop_iteration;
Damien429d7192013-10-04 19:53:11 +0100172
Damieneb19efb2013-10-10 22:06:54 +0100173// locals and globals need to be pointers because they can be the same in outer module scope
174py_map_t *map_locals;
175py_map_t *map_globals;
Damien429d7192013-10-04 19:53:11 +0100176py_map_t map_builtins;
177
178// approximatelly doubling primes; made with Mathematica command: Table[Prime[Floor[(1.7)^n]], {n, 3, 24}]
179static int doubling_primes[] = {7, 19, 43, 89, 179, 347, 647, 1229, 2297, 4243, 7829, 14347, 26017, 47149, 84947, 152443, 273253, 488399, 869927, 1547173, 2745121, 4861607};
180
181int get_doubling_prime_greater_or_equal_to(int x) {
182 for (int i = 0; i < sizeof(doubling_primes) / sizeof(int); i++) {
183 if (doubling_primes[i] >= x) {
184 return doubling_primes[i];
185 }
186 }
187 // ran out of primes in the table!
188 // return something sensible, at least make it odd
189 return x | 1;
190}
191
192void py_map_init(py_map_t *map, py_map_kind_t kind, int n) {
193 map->kind = kind;
Damien429d7192013-10-04 19:53:11 +0100194 map->used = 0;
Damienf086ecf2013-10-22 16:05:11 +0100195 map->alloc = get_doubling_prime_greater_or_equal_to(n + 1);
Damien5ac1b2e2013-10-18 19:58:12 +0100196 map->table = m_new0(py_map_elem_t, map->alloc);
Damien429d7192013-10-04 19:53:11 +0100197}
198
199py_map_t *py_map_new(py_map_kind_t kind, int n) {
200 py_map_t *map = m_new(py_map_t, 1);
201 py_map_init(map, kind, n);
202 return map;
203}
204
Damien5ac1b2e2013-10-18 19:58:12 +0100205machine_int_t py_obj_hash(py_obj_t o_in) {
206 if (o_in == py_const_false) {
207 return 0; // needs to hash to same as the integer 0, since False==0
208 } else if (o_in == py_const_true) {
209 return 1; // needs to hash to same as the integer 1, since True==1
210 } else if (IS_SMALL_INT(o_in)) {
Damien429d7192013-10-04 19:53:11 +0100211 return FROM_SMALL_INT(o_in);
Damien5ac1b2e2013-10-18 19:58:12 +0100212 } else if (IS_O(o_in, O_CONST)) {
213 return (machine_int_t)o_in;
Damien429d7192013-10-04 19:53:11 +0100214 } else if (IS_O(o_in, O_STR)) {
215 return ((py_obj_base_t*)o_in)->u_str;
216 } else {
217 assert(0);
218 return 0;
219 }
220}
221
Damien5ac1b2e2013-10-18 19:58:12 +0100222// this function implements the '==' operator (and so the inverse of '!=')
223// from the python language reference:
224// "The objects need not have the same type. If both are numbers, they are converted
225// to a common type. Otherwise, the == and != operators always consider objects of
226// different types to be unequal."
227// note also that False==0 and True==1 are true expressions
Damien429d7192013-10-04 19:53:11 +0100228bool py_obj_equal(py_obj_t o1, py_obj_t o2) {
229 if (o1 == o2) {
230 return true;
Damien5ac1b2e2013-10-18 19:58:12 +0100231 } else if (IS_SMALL_INT(o1) || IS_SMALL_INT(o2)) {
232 if (IS_SMALL_INT(o1) && IS_SMALL_INT(o2)) {
233 return false;
234 } else {
235 if (IS_SMALL_INT(o2)) {
236 py_obj_t temp = o1; o1 = o2; o2 = temp;
237 }
238 // o1 is the SMALL_INT, o2 is not
239 py_small_int_t val = FROM_SMALL_INT(o1);
240 if (o2 == py_const_false) {
241 return val == 0;
242 } else if (o2 == py_const_true) {
243 return val == 1;
244 } else {
245 return false;
246 }
247 }
Damien429d7192013-10-04 19:53:11 +0100248 } else if (IS_O(o1, O_STR) && IS_O(o2, O_STR)) {
249 return ((py_obj_base_t*)o1)->u_str == ((py_obj_base_t*)o2)->u_str;
250 } else {
251 assert(0);
252 return false;
253 }
254}
255
256py_map_elem_t* py_map_lookup_helper(py_map_t *map, py_obj_t index, bool add_if_not_found) {
257 bool is_map_py_obj = (map->kind == MAP_PY_OBJ);
258 machine_uint_t hash;
259 if (is_map_py_obj) {
260 hash = py_obj_hash(index);
261 } else {
262 hash = (machine_uint_t)index;
263 }
264 uint pos = hash % map->alloc;
265 for (;;) {
266 py_map_elem_t *elem = &map->table[pos];
267 if (elem->key == NULL) {
268 // not in table
269 if (add_if_not_found) {
270 if (map->used + 1 >= map->alloc) {
271 // not enough room in table, rehash it
272 int old_alloc = map->alloc;
273 py_map_elem_t *old_table = map->table;
274 map->alloc = get_doubling_prime_greater_or_equal_to(map->alloc + 1);
275 map->used = 0;
Damien5ac1b2e2013-10-18 19:58:12 +0100276 map->table = m_new0(py_map_elem_t, map->alloc);
Damien429d7192013-10-04 19:53:11 +0100277 for (int i = 0; i < old_alloc; i++) {
278 if (old_table[i].key != NULL) {
279 py_map_lookup_helper(map, old_table[i].key, true)->value = old_table[i].value;
280 }
281 }
282 m_free(old_table);
283 // restart the search for the new element
284 pos = hash % map->alloc;
285 } else {
286 map->used += 1;
287 elem->key = index;
288 return elem;
289 }
290 } else {
291 return NULL;
292 }
293 } else if (elem->key == index || (is_map_py_obj && py_obj_equal(elem->key, index))) {
294 // found it
Damien5ac1b2e2013-10-18 19:58:12 +0100295 /* it seems CPython does not replace the index; try x={True:'true'};x[1]='one';x
Damien429d7192013-10-04 19:53:11 +0100296 if (add_if_not_found) {
297 elem->key = index;
298 }
Damien5ac1b2e2013-10-18 19:58:12 +0100299 */
Damien429d7192013-10-04 19:53:11 +0100300 return elem;
301 } else {
302 // not yet found, keep searching in this table
303 pos = (pos + 1) % map->alloc;
304 }
305 }
306}
307
308py_map_elem_t* py_qstr_map_lookup(py_map_t *map, qstr index, bool add_if_not_found) {
309 py_obj_t o = (py_obj_t)(machine_uint_t)index;
310 return py_map_lookup_helper(map, o, add_if_not_found);
311}
312
313py_map_elem_t* py_map_lookup(py_obj_t o, py_obj_t index, bool add_if_not_found) {
314 assert(IS_O(o, O_MAP));
315 return py_map_lookup_helper(&((py_obj_base_t *)o)->u_map, index, add_if_not_found);
316}
317
318static bool fit_small_int(py_small_int_t o) {
319 return true;
320}
321
322py_obj_t py_obj_new_const(const char *id) {
323 py_obj_base_t *o = m_new(py_obj_base_t, 1);
324 o->kind = O_CONST;
325 o->id = id;
326 return (py_obj_t)o;
327}
328
329py_obj_t py_obj_new_str(qstr qstr) {
330 py_obj_base_t *o = m_new(py_obj_base_t, 1);
331 o->kind = O_STR;
332 o->u_str = qstr;
333 return (py_obj_t)o;
334}
335
Damien3ef4abb2013-10-12 16:53:13 +0100336#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100337py_obj_t py_obj_new_float(float_t val) {
338 py_obj_base_t *o = m_new(py_obj_base_t, 1);
339 o->kind = O_FLOAT;
Damiene4af64f2013-10-06 12:04:13 +0100340 o->u_flt = val;
Damien429d7192013-10-04 19:53:11 +0100341 return (py_obj_t)o;
342}
343#endif
344
Damience89a212013-10-15 22:25:17 +0100345py_obj_t py_obj_new_exception_0(qstr id) {
346 py_obj_base_t *o = m_new(py_obj_base_t, 1);
347 o->kind = O_EXCEPTION_0;
348 o->u_exc0.id = id;
349 return (py_obj_t)o;
350}
351
352py_obj_t py_obj_new_exception_2(qstr id, const char *fmt, const char *s1, const char *s2) {
353 py_obj_base_t *o = m_new(py_obj_base_t, 1);
Damienf086ecf2013-10-22 16:05:11 +0100354 o->kind = O_EXCEPTION_N;
355 o->u_exc_n.id = id;
356 o->u_exc_n.n_args = 3;
357 o->u_exc_n.args = m_new(const void*, 3);
358 o->u_exc_n.args[0] = fmt;
359 o->u_exc_n.args[1] = s1;
360 o->u_exc_n.args[2] = s2;
Damience89a212013-10-15 22:25:17 +0100361 return (py_obj_t)o;
362}
363
364// range is a class and instances are immutable sequence objects
365py_obj_t py_obj_new_range(int start, int stop, int step) {
366 py_obj_base_t *o = m_new(py_obj_base_t, 1);
367 o->kind = O_RANGE;
368 o->u_range.start = start;
369 o->u_range.stop = stop;
370 o->u_range.step = step;
371 return o;
372}
373
374py_obj_t py_obj_new_range_iterator(int cur, int stop, int step) {
375 py_obj_base_t *o = m_new(py_obj_base_t, 1);
376 o->kind = O_RANGE_IT;
377 o->u_range_it.cur = cur;
378 o->u_range_it.stop = stop;
379 o->u_range_it.step = step;
380 return o;
381}
382
Damienc226dca2013-10-16 16:12:52 +0100383py_obj_t py_obj_new_tuple_iterator(py_obj_base_t *tuple, int cur) {
384 py_obj_base_t *o = m_new(py_obj_base_t, 1);
385 o->kind = O_TUPLE_IT;
386 o->u_tuple_list_it.obj = tuple;
387 o->u_tuple_list_it.cur = cur;
388 return o;
389}
390
391py_obj_t py_obj_new_list_iterator(py_obj_base_t *list, int cur) {
392 py_obj_base_t *o = m_new(py_obj_base_t, 1);
393 o->kind = O_LIST_IT;
394 o->u_tuple_list_it.obj = list;
395 o->u_tuple_list_it.cur = cur;
396 return o;
397}
398
399py_obj_t rt_list_append(py_obj_t self_in, py_obj_t arg) {
Damien429d7192013-10-04 19:53:11 +0100400 assert(IS_O(self_in, O_LIST));
401 py_obj_base_t *self = self_in;
Damienc226dca2013-10-16 16:12:52 +0100402 if (self->u_tuple_list.len >= self->u_tuple_list.alloc) {
403 self->u_tuple_list.alloc *= 2;
404 self->u_tuple_list.items = m_renew(py_obj_t, self->u_tuple_list.items, self->u_tuple_list.alloc);
Damien429d7192013-10-04 19:53:11 +0100405 }
Damienc226dca2013-10-16 16:12:52 +0100406 self->u_tuple_list.items[self->u_tuple_list.len++] = arg;
Damien429d7192013-10-04 19:53:11 +0100407 return arg;
408}
409
Damienbd254452013-10-16 20:39:12 +0100410py_obj_t rt_gen_instance_next(py_obj_t self_in) {
411 py_obj_t ret = rt_iternext(self_in);
412 if (ret == py_const_stop_iteration) {
413 nlr_jump(py_obj_new_exception_0(qstr_from_str_static("StopIteration")));
414 } else {
415 return ret;
416 }
417}
418
Damien429d7192013-10-04 19:53:11 +0100419static qstr q_append;
420static qstr q_print;
421static qstr q_len;
422static qstr q___build_class__;
Damienbd254452013-10-16 20:39:12 +0100423static qstr q___next__;
Damience89a212013-10-15 22:25:17 +0100424static qstr q_AttributeError;
Damienc226dca2013-10-16 16:12:52 +0100425static qstr q_IndexError;
Damien5ac1b2e2013-10-18 19:58:12 +0100426static qstr q_KeyError;
Damience89a212013-10-15 22:25:17 +0100427static qstr q_NameError;
428static qstr q_TypeError;
Damien429d7192013-10-04 19:53:11 +0100429
430typedef enum {
Damien826005c2013-10-05 23:17:28 +0100431 PY_CODE_NONE,
Damien429d7192013-10-04 19:53:11 +0100432 PY_CODE_BYTE,
Damien826005c2013-10-05 23:17:28 +0100433 PY_CODE_NATIVE,
434 PY_CODE_INLINE_ASM,
Damien429d7192013-10-04 19:53:11 +0100435} py_code_kind_t;
436
437typedef struct _py_code_t {
438 py_code_kind_t kind;
439 int n_args;
Damienbd254452013-10-16 20:39:12 +0100440 int n_locals;
441 int n_stack;
442 bool is_generator;
Damien429d7192013-10-04 19:53:11 +0100443 union {
444 struct {
Damien429d7192013-10-04 19:53:11 +0100445 byte *code;
446 uint len;
447 } u_byte;
Damien826005c2013-10-05 23:17:28 +0100448 struct {
449 py_fun_t fun;
450 } u_native;
451 struct {
Damiene4af64f2013-10-06 12:04:13 +0100452 void *fun;
Damien826005c2013-10-05 23:17:28 +0100453 } u_inline_asm;
Damien429d7192013-10-04 19:53:11 +0100454 };
455} py_code_t;
456
457static int next_unique_code_id;
458static py_code_t *unique_codes;
459
460py_obj_t fun_list_append;
Damienbd254452013-10-16 20:39:12 +0100461py_obj_t fun_gen_instance_next;
Damien429d7192013-10-04 19:53:11 +0100462
Damien5ac1b2e2013-10-18 19:58:12 +0100463py_obj_t py_builtin___repl_print__(py_obj_t o) {
464 if (o != py_const_none) {
465 py_obj_print(o);
466 printf("\n");
467 }
468 return py_const_none;
469}
470
Damien429d7192013-10-04 19:53:11 +0100471py_obj_t py_builtin_print(py_obj_t o) {
472 if (IS_O(o, O_STR)) {
473 // special case, print string raw
474 printf("%s\n", qstr_str(((py_obj_base_t*)o)->u_str));
475 } else {
476 // print the object Python style
477 py_obj_print(o);
478 printf("\n");
479 }
480 return py_const_none;
481}
482
483py_obj_t py_builtin_len(py_obj_t o_in) {
484 py_small_int_t len = 0;
Damienc226dca2013-10-16 16:12:52 +0100485 if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) {
Damien429d7192013-10-04 19:53:11 +0100486 py_obj_base_t *o = o_in;
Damienc226dca2013-10-16 16:12:52 +0100487 len = o->u_tuple_list.len;
Damien429d7192013-10-04 19:53:11 +0100488 } else if (IS_O(o_in, O_MAP)) {
489 py_obj_base_t *o = o_in;
490 len = o->u_map.used;
491 } else {
492 assert(0);
493 }
494 return TO_SMALL_INT(len);
495}
496
Damiena3977762013-10-09 23:10:10 +0100497py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name) {
498 // we differ from CPython: we set the new __locals__ object here
Damieneb19efb2013-10-10 22:06:54 +0100499 py_map_t *old_locals = map_locals;
Damiena3977762013-10-09 23:10:10 +0100500 py_map_t *class_locals = py_map_new(MAP_QSTR, 0);
Damieneb19efb2013-10-10 22:06:54 +0100501 map_locals = class_locals;
Damiena3977762013-10-09 23:10:10 +0100502
503 // call the class code
504 rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef);
505
506 // restore old __locals__ object
507 map_locals = old_locals;
508
509 // create and return the new class
Damien429d7192013-10-04 19:53:11 +0100510 py_obj_base_t *o = m_new(py_obj_base_t, 1);
511 o->kind = O_CLASS;
Damiena3977762013-10-09 23:10:10 +0100512 o->u_class.locals = class_locals;
Damien429d7192013-10-04 19:53:11 +0100513 return o;
514}
515
Damience89a212013-10-15 22:25:17 +0100516py_obj_t py_builtin_range(py_obj_t o_arg) {
Damien9fc79332013-10-23 00:01:10 +0100517 return py_obj_new_range(0, py_get_int(o_arg), 1);
Damience89a212013-10-15 22:25:17 +0100518}
519
Damiena1ddfcc2013-10-10 23:25:50 +0100520#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100521FILE *fp_native = NULL;
Damiena1ddfcc2013-10-10 23:25:50 +0100522#endif
Damien429d7192013-10-04 19:53:11 +0100523
Damien8b3a7c22013-10-23 20:20:17 +0100524void rt_init(void) {
Damien429d7192013-10-04 19:53:11 +0100525 q_append = qstr_from_str_static("append");
526 q_print = qstr_from_str_static("print");
527 q_len = qstr_from_str_static("len");
528 q___build_class__ = qstr_from_str_static("__build_class__");
Damienbd254452013-10-16 20:39:12 +0100529 q___next__ = qstr_from_str_static("__next__");
Damience89a212013-10-15 22:25:17 +0100530 q_AttributeError = qstr_from_str_static("AttributeError");
Damienc226dca2013-10-16 16:12:52 +0100531 q_IndexError = qstr_from_str_static("IndexError");
Damien5ac1b2e2013-10-18 19:58:12 +0100532 q_KeyError = qstr_from_str_static("KeyError");
Damience89a212013-10-15 22:25:17 +0100533 q_NameError = qstr_from_str_static("NameError");
534 q_TypeError = qstr_from_str_static("TypeError");
Damien429d7192013-10-04 19:53:11 +0100535
536 py_const_none = py_obj_new_const("None");
537 py_const_false = py_obj_new_const("False");
538 py_const_true = py_obj_new_const("True");
Damience89a212013-10-15 22:25:17 +0100539 py_const_stop_iteration = py_obj_new_const("StopIteration");
Damien429d7192013-10-04 19:53:11 +0100540
Damieneb19efb2013-10-10 22:06:54 +0100541 // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
542 map_locals = map_globals = py_map_new(MAP_QSTR, 1);
543 py_qstr_map_lookup(map_globals, qstr_from_str_static("__name__"), true)->value = py_obj_new_str(qstr_from_str_static("__main__"));
Damien429d7192013-10-04 19:53:11 +0100544
545 py_map_init(&map_builtins, MAP_QSTR, 3);
Damien5ac1b2e2013-10-18 19:58:12 +0100546 py_qstr_map_lookup(&map_builtins, qstr_from_str_static("__repl_print__"), true)->value = rt_make_function_1(py_builtin___repl_print__);
Damien429d7192013-10-04 19:53:11 +0100547 py_qstr_map_lookup(&map_builtins, q_print, true)->value = rt_make_function_1(py_builtin_print);
548 py_qstr_map_lookup(&map_builtins, q_len, true)->value = rt_make_function_1(py_builtin_len);
549 py_qstr_map_lookup(&map_builtins, q___build_class__, true)->value = rt_make_function_2(py_builtin___build_class__);
Damience89a212013-10-15 22:25:17 +0100550 py_qstr_map_lookup(&map_builtins, qstr_from_str_static("range"), true)->value = rt_make_function_1(py_builtin_range);
Damien429d7192013-10-04 19:53:11 +0100551
Damien5ac1b2e2013-10-18 19:58:12 +0100552 next_unique_code_id = 2; // 1 is reserved for the __main__ module scope
Damien429d7192013-10-04 19:53:11 +0100553 unique_codes = NULL;
554
Damienc226dca2013-10-16 16:12:52 +0100555 fun_list_append = rt_make_function_2(rt_list_append);
Damienbd254452013-10-16 20:39:12 +0100556 fun_gen_instance_next = rt_make_function_1(rt_gen_instance_next);
Damien429d7192013-10-04 19:53:11 +0100557
Damiena1ddfcc2013-10-10 23:25:50 +0100558#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100559 fp_native = fopen("out-native", "wb");
Damiena1ddfcc2013-10-10 23:25:50 +0100560#endif
Damien429d7192013-10-04 19:53:11 +0100561}
562
Damien8b3a7c22013-10-23 20:20:17 +0100563void rt_deinit(void) {
Damiena1ddfcc2013-10-10 23:25:50 +0100564#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100565 if (fp_native != NULL) {
566 fclose(fp_native);
567 }
Damiena1ddfcc2013-10-10 23:25:50 +0100568#endif
Damien429d7192013-10-04 19:53:11 +0100569}
570
Damien5ac1b2e2013-10-18 19:58:12 +0100571int rt_get_unique_code_id(bool is_main_module) {
572 if (is_main_module) {
573 return 1;
574 } else {
575 return next_unique_code_id++;
576 }
Damien429d7192013-10-04 19:53:11 +0100577}
578
Damien8b3a7c22013-10-23 20:20:17 +0100579static void alloc_unique_codes(void) {
Damien429d7192013-10-04 19:53:11 +0100580 if (unique_codes == NULL) {
581 unique_codes = m_new(py_code_t, next_unique_code_id);
Damien826005c2013-10-05 23:17:28 +0100582 for (int i = 0; i < next_unique_code_id; i++) {
583 unique_codes[i].kind = PY_CODE_NONE;
584 }
Damien429d7192013-10-04 19:53:11 +0100585 }
Damien826005c2013-10-05 23:17:28 +0100586}
587
Damienbd254452013-10-16 20:39:12 +0100588void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args, int n_locals, int n_stack, bool is_generator) {
Damien826005c2013-10-05 23:17:28 +0100589 alloc_unique_codes();
590
591 assert(unique_code_id < next_unique_code_id);
592 unique_codes[unique_code_id].kind = PY_CODE_BYTE;
593 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +0100594 unique_codes[unique_code_id].n_locals = n_locals;
595 unique_codes[unique_code_id].n_stack = n_stack;
596 unique_codes[unique_code_id].is_generator = is_generator;
Damien826005c2013-10-05 23:17:28 +0100597 unique_codes[unique_code_id].u_byte.code = code;
598 unique_codes[unique_code_id].u_byte.len = len;
599
600 DEBUG_printf("assign byte code: id=%d code=%p len=%u n_args=%d\n", unique_code_id, code, len, n_args);
601}
602
603void rt_assign_native_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
604 alloc_unique_codes();
605
Damienb05d7072013-10-05 13:37:10 +0100606 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
Damien429d7192013-10-04 19:53:11 +0100607 unique_codes[unique_code_id].kind = PY_CODE_NATIVE;
608 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +0100609 unique_codes[unique_code_id].n_locals = 0;
610 unique_codes[unique_code_id].n_stack = 0;
611 unique_codes[unique_code_id].is_generator = false;
Damien429d7192013-10-04 19:53:11 +0100612 unique_codes[unique_code_id].u_native.fun = fun;
613
Damiena1ddfcc2013-10-10 23:25:50 +0100614#ifdef DEBUG_PRINT
Damien429d7192013-10-04 19:53:11 +0100615 DEBUG_printf("assign native code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
616 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
617 for (int i = 0; i < 128 && i < len; i++) {
618 if (i > 0 && i % 16 == 0) {
619 DEBUG_printf("\n");
620 }
621 DEBUG_printf(" %02x", fun_data[i]);
622 }
623 DEBUG_printf("\n");
624
Damiena1ddfcc2013-10-10 23:25:50 +0100625#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100626 if (fp_native != NULL) {
627 fwrite(fun_data, len, 1, fp_native);
Damien13ed3a62013-10-08 09:05:10 +0100628 fflush(fp_native);
Damien429d7192013-10-04 19:53:11 +0100629 }
Damiena1ddfcc2013-10-10 23:25:50 +0100630#endif
631#endif
Damien429d7192013-10-04 19:53:11 +0100632}
633
Damien826005c2013-10-05 23:17:28 +0100634void rt_assign_inline_asm_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
635 alloc_unique_codes();
Damien429d7192013-10-04 19:53:11 +0100636
Damien826005c2013-10-05 23:17:28 +0100637 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
638 unique_codes[unique_code_id].kind = PY_CODE_INLINE_ASM;
639 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +0100640 unique_codes[unique_code_id].n_locals = 0;
641 unique_codes[unique_code_id].n_stack = 0;
642 unique_codes[unique_code_id].is_generator = false;
Damien826005c2013-10-05 23:17:28 +0100643 unique_codes[unique_code_id].u_inline_asm.fun = fun;
644
Damiena1ddfcc2013-10-10 23:25:50 +0100645#ifdef DEBUG_PRINT
Damien826005c2013-10-05 23:17:28 +0100646 DEBUG_printf("assign inline asm code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
647 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
648 for (int i = 0; i < 128 && i < len; i++) {
649 if (i > 0 && i % 16 == 0) {
650 DEBUG_printf("\n");
651 }
652 DEBUG_printf(" %02x", fun_data[i]);
653 }
654 DEBUG_printf("\n");
655
Damiena1ddfcc2013-10-10 23:25:50 +0100656#ifdef WRITE_NATIVE
Damien826005c2013-10-05 23:17:28 +0100657 if (fp_native != NULL) {
658 fwrite(fun_data, len, 1, fp_native);
659 }
Damiena1ddfcc2013-10-10 23:25:50 +0100660#endif
661#endif
Damien429d7192013-10-04 19:53:11 +0100662}
663
Damiena3977762013-10-09 23:10:10 +0100664bool py_obj_is_callable(py_obj_t o_in) {
665 if (IS_SMALL_INT(o_in)) {
666 return false;
667 } else {
668 py_obj_base_t *o = o_in;
669 switch (o->kind) {
670 case O_FUN_0:
671 case O_FUN_1:
672 case O_FUN_2:
673 case O_FUN_N:
674 case O_FUN_BC:
675 case O_FUN_ASM:
Damieneb19efb2013-10-10 22:06:54 +0100676 // what about O_CLASS, and an O_OBJ that has a __call__ method?
Damiena3977762013-10-09 23:10:10 +0100677 return true;
678 default:
679 return false;
680 }
681 }
682}
683
Damien429d7192013-10-04 19:53:11 +0100684const char *py_obj_get_type_str(py_obj_t o_in) {
685 if (IS_SMALL_INT(o_in)) {
686 return "int";
687 } else {
688 py_obj_base_t *o = o_in;
689 switch (o->kind) {
690 case O_CONST:
691 if (o == py_const_none) {
692 return "NoneType";
693 } else {
694 return "bool";
695 }
696 case O_STR:
697 return "str";
Damien3ef4abb2013-10-12 16:53:13 +0100698#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100699 case O_FLOAT:
700 return "float";
701#endif
Damien6cdd3af2013-10-05 18:08:26 +0100702 case O_FUN_0:
703 case O_FUN_1:
704 case O_FUN_2:
705 case O_FUN_N:
706 case O_FUN_BC:
707 return "function";
Damienbd254452013-10-16 20:39:12 +0100708 case O_GEN_INSTANCE:
709 return "generator";
Damienc226dca2013-10-16 16:12:52 +0100710 case O_TUPLE:
711 return "tuple";
Damien429d7192013-10-04 19:53:11 +0100712 case O_LIST:
713 return "list";
Damienc226dca2013-10-16 16:12:52 +0100714 case O_TUPLE_IT:
715 return "tuple_iterator";
716 case O_LIST_IT:
717 return "list_iterator";
Damien429d7192013-10-04 19:53:11 +0100718 case O_SET:
719 return "set";
720 case O_MAP:
721 return "dict";
Damiena3977762013-10-09 23:10:10 +0100722 case O_OBJ:
723 {
724 py_map_elem_t *qn = py_qstr_map_lookup(o->u_obj.class->u_class.locals, qstr_from_str_static("__qualname__"), false);
725 assert(qn != NULL);
726 assert(IS_O(qn->value, O_STR));
727 return qstr_str(((py_obj_base_t*)qn->value)->u_str);
728 }
Damien429d7192013-10-04 19:53:11 +0100729 default:
730 assert(0);
731 return "UnknownType";
732 }
733 }
734}
735
736void py_obj_print(py_obj_t o_in) {
737 if (IS_SMALL_INT(o_in)) {
738 printf("%d", (int)FROM_SMALL_INT(o_in));
739 } else {
740 py_obj_base_t *o = o_in;
741 switch (o->kind) {
742 case O_CONST:
743 printf("%s", o->id);
744 break;
745 case O_STR:
746 // TODO need to escape chars etc
747 printf("'%s'", qstr_str(o->u_str));
748 break;
Damien3ef4abb2013-10-12 16:53:13 +0100749#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100750 case O_FLOAT:
Damiene4af64f2013-10-06 12:04:13 +0100751 printf("%f", o->u_flt);
Damien429d7192013-10-04 19:53:11 +0100752 break;
753#endif
Damienbd254452013-10-16 20:39:12 +0100754 case O_EXCEPTION_0:
755 printf("%s", qstr_str(o->u_exc0.id));
756 break;
Damienf086ecf2013-10-22 16:05:11 +0100757 case O_EXCEPTION_N:
758 printf("%s: ", qstr_str(o->u_exc_n.id));
759 printf(o->u_exc_n.args[0], o->u_exc_n.args[1], o->u_exc_n.args[2]);
Damience89a212013-10-15 22:25:17 +0100760 break;
Damienbd254452013-10-16 20:39:12 +0100761 case O_GEN_INSTANCE:
762 printf("<generator object 'fun-name' at %p>", o);
763 break;
Damienc226dca2013-10-16 16:12:52 +0100764 case O_TUPLE:
765 printf("(");
766 for (int i = 0; i < o->u_tuple_list.len; i++) {
Damien429d7192013-10-04 19:53:11 +0100767 if (i > 0) {
768 printf(", ");
769 }
Damienc226dca2013-10-16 16:12:52 +0100770 py_obj_print(o->u_tuple_list.items[i]);
771 }
772 if (o->u_tuple_list.len == 1) {
773 printf(",");
774 }
775 printf(")");
776 break;
777 case O_LIST:
778 printf("[");
779 for (int i = 0; i < o->u_tuple_list.len; i++) {
780 if (i > 0) {
781 printf(", ");
782 }
783 py_obj_print(o->u_tuple_list.items[i]);
Damien429d7192013-10-04 19:53:11 +0100784 }
785 printf("]");
786 break;
787 case O_SET:
788 {
789 bool first = true;
790 printf("{");
791 for (int i = 0; i < o->u_set.alloc; i++) {
792 if (o->u_set.table[i] != NULL) {
793 if (!first) {
794 printf(", ");
795 }
796 first = false;
797 py_obj_print(o->u_set.table[i]);
798 }
799 }
800 printf("}");
801 break;
802 }
803 case O_MAP:
804 {
805 bool first = true;
806 printf("{");
807 for (int i = 0; i < o->u_map.alloc; i++) {
808 if (o->u_map.table[i].key != NULL) {
809 if (!first) {
810 printf(", ");
811 }
812 first = false;
813 py_obj_print(o->u_map.table[i].key);
814 printf(": ");
815 py_obj_print(o->u_map.table[i].value);
816 }
817 }
818 printf("}");
819 break;
820 }
821 default:
Damiena3977762013-10-09 23:10:10 +0100822 printf("<? %d>", o->kind);
Damien429d7192013-10-04 19:53:11 +0100823 assert(0);
824 }
825 }
826}
827
828int rt_is_true(py_obj_t arg) {
829 DEBUG_OP_printf("is true %p\n", arg);
830 if (IS_SMALL_INT(arg)) {
831 if (FROM_SMALL_INT(arg) == 0) {
832 return 0;
833 } else {
834 return 1;
835 }
836 } else if (arg == py_const_none) {
837 return 0;
838 } else if (arg == py_const_false) {
839 return 0;
840 } else if (arg == py_const_true) {
841 return 1;
842 } else {
843 assert(0);
844 return 0;
845 }
846}
847
Damien9fc79332013-10-23 00:01:10 +0100848int py_get_int(py_obj_t arg) {
Damienc226dca2013-10-16 16:12:52 +0100849 if (arg == py_const_false) {
850 return 0;
851 } else if (arg == py_const_true) {
852 return 1;
853 } else if (IS_SMALL_INT(arg)) {
Damien429d7192013-10-04 19:53:11 +0100854 return FROM_SMALL_INT(arg);
855 } else {
856 assert(0);
857 return 0;
858 }
859}
860
Damien9fc79332013-10-23 00:01:10 +0100861qstr py_get_qstr(py_obj_t arg) {
862 if (IS_O(arg, O_STR)) {
863 return ((py_obj_base_t*)arg)->u_str;
864 } else {
865 assert(0);
866 return 0;
867 }
868}
869
Damien429d7192013-10-04 19:53:11 +0100870py_obj_t rt_load_const_str(qstr qstr) {
871 DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
872 return py_obj_new_str(qstr);
873}
874
875py_obj_t rt_load_name(qstr qstr) {
876 // logic: search locals, globals, builtins
Damiena3977762013-10-09 23:10:10 +0100877 DEBUG_OP_printf("load name %s\n", qstr_str(qstr));
Damieneb19efb2013-10-10 22:06:54 +0100878 py_map_elem_t *elem = py_qstr_map_lookup(map_locals, qstr, false);
Damiena3977762013-10-09 23:10:10 +0100879 if (elem == NULL) {
Damieneb19efb2013-10-10 22:06:54 +0100880 elem = py_qstr_map_lookup(map_globals, qstr, false);
Damiena3977762013-10-09 23:10:10 +0100881 if (elem == NULL) {
882 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
883 if (elem == NULL) {
Damience89a212013-10-15 22:25:17 +0100884 nlr_jump(py_obj_new_exception_2(q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL));
Damiena3977762013-10-09 23:10:10 +0100885 }
886 }
887 }
888 return elem->value;
889}
890
891py_obj_t rt_load_global(qstr qstr) {
892 // logic: search globals, builtins
893 DEBUG_OP_printf("load global %s\n", qstr_str(qstr));
Damieneb19efb2013-10-10 22:06:54 +0100894 py_map_elem_t *elem = py_qstr_map_lookup(map_globals, qstr, false);
Damien429d7192013-10-04 19:53:11 +0100895 if (elem == NULL) {
896 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
897 if (elem == NULL) {
Damience89a212013-10-15 22:25:17 +0100898 nlr_jump(py_obj_new_exception_2(q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL));
Damien429d7192013-10-04 19:53:11 +0100899 }
900 }
901 return elem->value;
902}
903
Damien8b3a7c22013-10-23 20:20:17 +0100904py_obj_t rt_load_build_class(void) {
Damien429d7192013-10-04 19:53:11 +0100905 DEBUG_OP_printf("load_build_class\n");
906 py_map_elem_t *elem = py_qstr_map_lookup(&map_builtins, q___build_class__, false);
907 if (elem == NULL) {
908 printf("name doesn't exist: __build_class__\n");
909 assert(0);
910 }
911 return elem->value;
912}
913
914void rt_store_name(qstr qstr, py_obj_t obj) {
Damiena3977762013-10-09 23:10:10 +0100915 DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qstr), obj);
Damieneb19efb2013-10-10 22:06:54 +0100916 py_qstr_map_lookup(map_locals, qstr, true)->value = obj;
Damiena3977762013-10-09 23:10:10 +0100917}
918
919void rt_store_global(qstr qstr, py_obj_t obj) {
920 DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qstr), obj);
Damieneb19efb2013-10-10 22:06:54 +0100921 py_qstr_map_lookup(map_globals, qstr, true)->value = obj;
Damien429d7192013-10-04 19:53:11 +0100922}
923
924py_obj_t rt_unary_op(int op, py_obj_t arg) {
925 assert(0);
926 return py_const_none;
927}
928
Damienc226dca2013-10-16 16:12:52 +0100929uint get_index(py_obj_base_t *base, py_obj_t index) {
930 // assumes base is O_TUPLE or O_LIST
931 // TODO False and True are considered 0 and 1 for indexing purposes
932 int len = base->u_tuple_list.len;
933 if (IS_SMALL_INT(index)) {
934 int i = FROM_SMALL_INT(index);
935 if (i < 0) {
936 i += len;
937 }
938 if (i < 0 || i >= len) {
939 nlr_jump(py_obj_new_exception_2(q_IndexError, "%s index out of range", py_obj_get_type_str(base), NULL));
940 }
941 return i;
942 } else {
943 nlr_jump(py_obj_new_exception_2(q_TypeError, "%s indices must be integers, not %s", py_obj_get_type_str(base), py_obj_get_type_str(index)));
944 }
945}
946
Damien429d7192013-10-04 19:53:11 +0100947py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs) {
948 DEBUG_OP_printf("binary %d %p %p\n", op, lhs, rhs);
949 if (op == RT_BINARY_OP_SUBSCR) {
Damienc226dca2013-10-16 16:12:52 +0100950 if ((IS_O(lhs, O_TUPLE) || IS_O(lhs, O_LIST))) {
Damien5ac1b2e2013-10-18 19:58:12 +0100951 // tuple/list load
Damienc226dca2013-10-16 16:12:52 +0100952 uint index = get_index(lhs, rhs);
953 return ((py_obj_base_t*)lhs)->u_tuple_list.items[index];
Damien5ac1b2e2013-10-18 19:58:12 +0100954 } else if (IS_O(lhs, O_MAP)) {
955 // map load
956 py_map_elem_t *elem = py_map_lookup(lhs, rhs, false);
957 if (elem == NULL) {
958 nlr_jump(py_obj_new_exception_2(q_KeyError, "<value>", NULL, NULL));
959 } else {
960 return elem->value;
961 }
Damien429d7192013-10-04 19:53:11 +0100962 } else {
963 assert(0);
964 }
965 } else if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
966 py_small_int_t val;
967 switch (op) {
Damien7b2d3f32013-10-22 16:53:02 +0100968 case RT_BINARY_OP_OR:
969 case RT_BINARY_OP_INPLACE_OR: val = FROM_SMALL_INT(lhs) | FROM_SMALL_INT(rhs); break;
970 case RT_BINARY_OP_XOR:
971 case RT_BINARY_OP_INPLACE_XOR: val = FROM_SMALL_INT(lhs) ^ FROM_SMALL_INT(rhs); break;
972 case RT_BINARY_OP_AND:
973 case RT_BINARY_OP_INPLACE_AND: val = FROM_SMALL_INT(lhs) & FROM_SMALL_INT(rhs); break;
974 case RT_BINARY_OP_LSHIFT:
975 case RT_BINARY_OP_INPLACE_LSHIFT: val = FROM_SMALL_INT(lhs) << FROM_SMALL_INT(rhs); break;
976 case RT_BINARY_OP_RSHIFT:
977 case RT_BINARY_OP_INPLACE_RSHIFT: val = FROM_SMALL_INT(lhs) >> FROM_SMALL_INT(rhs); break;
Damien429d7192013-10-04 19:53:11 +0100978 case RT_BINARY_OP_ADD:
979 case RT_BINARY_OP_INPLACE_ADD: val = FROM_SMALL_INT(lhs) + FROM_SMALL_INT(rhs); break;
Damienbd254452013-10-16 20:39:12 +0100980 case RT_BINARY_OP_SUBTRACT:
981 case RT_BINARY_OP_INPLACE_SUBTRACT: val = FROM_SMALL_INT(lhs) - FROM_SMALL_INT(rhs); break;
Damien7b2d3f32013-10-22 16:53:02 +0100982 case RT_BINARY_OP_MULTIPLY:
983 case RT_BINARY_OP_INPLACE_MULTIPLY: val = FROM_SMALL_INT(lhs) * FROM_SMALL_INT(rhs); break;
984 case RT_BINARY_OP_FLOOR_DIVIDE:
985 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = FROM_SMALL_INT(lhs) / FROM_SMALL_INT(rhs); break;
Damien3ef4abb2013-10-12 16:53:13 +0100986#if MICROPY_ENABLE_FLOAT
Damien7b2d3f32013-10-22 16:53:02 +0100987 case RT_BINARY_OP_TRUE_DIVIDE:
988 case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: return py_obj_new_float((float_t)FROM_SMALL_INT(lhs) / (float_t)FROM_SMALL_INT(rhs));
Damien429d7192013-10-04 19:53:11 +0100989#endif
990 default: printf("%d\n", op); assert(0); val = 0;
991 }
992 if (fit_small_int(val)) {
993 return TO_SMALL_INT(val);
994 }
995 } else if (IS_O(lhs, O_STR) && IS_O(rhs, O_STR)) {
996 const char *lhs_str = qstr_str(((py_obj_base_t*)lhs)->u_str);
997 const char *rhs_str = qstr_str(((py_obj_base_t*)rhs)->u_str);
998 char *val;
999 switch (op) {
1000 case RT_BINARY_OP_ADD:
1001 case RT_BINARY_OP_INPLACE_ADD: val = m_new(char, strlen(lhs_str) + strlen(rhs_str) + 1); strcpy(val, lhs_str); strcat(val, rhs_str); break;
1002 default: printf("%d\n", op); assert(0); val = NULL;
1003 }
1004 return py_obj_new_str(qstr_from_str_take(val));
1005 }
1006 assert(0);
1007 return py_const_none;
1008}
1009
1010py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs) {
1011 DEBUG_OP_printf("compare %d %p %p\n", op, lhs, rhs);
Damien7b2d3f32013-10-22 16:53:02 +01001012
1013 // deal with == and !=
1014 if (op == RT_COMPARE_OP_EQUAL || op == RT_COMPARE_OP_NOT_EQUAL) {
1015 if (py_obj_equal(lhs, rhs)) {
1016 if (op == RT_COMPARE_OP_EQUAL) {
1017 return py_const_true;
1018 } else {
1019 return py_const_false;
1020 }
1021 } else {
1022 if (op == RT_COMPARE_OP_EQUAL) {
1023 return py_const_false;
1024 } else {
1025 return py_const_true;
1026 }
1027 }
1028 }
1029
1030 // deal with small ints
Damien429d7192013-10-04 19:53:11 +01001031 if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
1032 int cmp;
1033 switch (op) {
1034 case RT_COMPARE_OP_LESS: cmp = FROM_SMALL_INT(lhs) < FROM_SMALL_INT(rhs); break;
1035 case RT_COMPARE_OP_MORE: cmp = FROM_SMALL_INT(lhs) > FROM_SMALL_INT(rhs); break;
Damien7b2d3f32013-10-22 16:53:02 +01001036 case RT_COMPARE_OP_LESS_EQUAL: cmp = FROM_SMALL_INT(lhs) <= FROM_SMALL_INT(rhs); break;
1037 case RT_COMPARE_OP_MORE_EQUAL: cmp = FROM_SMALL_INT(lhs) >= FROM_SMALL_INT(rhs); break;
Damien429d7192013-10-04 19:53:11 +01001038 default: assert(0); cmp = 0;
1039 }
1040 if (cmp) {
1041 return py_const_true;
1042 } else {
1043 return py_const_false;
1044 }
1045 }
Damien7b2d3f32013-10-22 16:53:02 +01001046
1047 // not implemented
Damien429d7192013-10-04 19:53:11 +01001048 assert(0);
1049 return py_const_none;
1050}
1051
1052py_obj_t rt_make_function_from_id(int unique_code_id) {
Damienb05d7072013-10-05 13:37:10 +01001053 DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id);
1054 if (unique_code_id < 1 || unique_code_id >= next_unique_code_id) {
Damien429d7192013-10-04 19:53:11 +01001055 // illegal code id
1056 return py_const_none;
1057 }
1058 py_code_t *c = &unique_codes[unique_code_id];
1059 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1060 switch (c->kind) {
Damien826005c2013-10-05 23:17:28 +01001061 case PY_CODE_BYTE:
1062 o->kind = O_FUN_BC;
1063 o->u_fun_bc.n_args = c->n_args;
1064 o->u_fun_bc.code = c->u_byte.code;
1065 o->u_fun_bc.len = c->u_byte.len;
1066 break;
Damien429d7192013-10-04 19:53:11 +01001067 case PY_CODE_NATIVE:
1068 switch (c->n_args) {
1069 case 0: o->kind = O_FUN_0; break;
1070 case 1: o->kind = O_FUN_1; break;
1071 case 2: o->kind = O_FUN_2; break;
1072 default: assert(0);
1073 }
1074 o->u_fun.fun = c->u_native.fun;
1075 break;
Damien826005c2013-10-05 23:17:28 +01001076 case PY_CODE_INLINE_ASM:
1077 o->kind = O_FUN_ASM;
1078 o->u_fun_asm.n_args = c->n_args;
1079 o->u_fun_asm.fun = c->u_inline_asm.fun;
Damien429d7192013-10-04 19:53:11 +01001080 break;
1081 default:
1082 assert(0);
1083 }
Damienbd254452013-10-16 20:39:12 +01001084
1085 // check for generator functions and if so wrap in generator object
1086 if (c->is_generator) {
1087 py_obj_base_t *o2 = m_new(py_obj_base_t, 1);
1088 o2->kind = O_GEN_WRAP;
1089 // we have at least 3 locals so the bc can write back fast[0,1,2] safely; should improve how this is done
1090 o2->u_gen_wrap.n_state = (c->n_locals < 3 ? 3 : c->n_locals) + c->n_stack;
1091 o2->u_gen_wrap.fun = o;
1092 o = o2;
1093 }
1094
Damien429d7192013-10-04 19:53:11 +01001095 return o;
1096}
1097
1098py_obj_t rt_make_function_0(py_fun_0_t fun) {
1099 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1100 o->kind = O_FUN_0;
1101 o->u_fun.fun = fun;
1102 return o;
1103}
1104
1105py_obj_t rt_make_function_1(py_fun_1_t fun) {
1106 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1107 o->kind = O_FUN_1;
1108 o->u_fun.fun = fun;
1109 return o;
1110}
1111
1112py_obj_t rt_make_function_2(py_fun_2_t fun) {
1113 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1114 o->kind = O_FUN_2;
1115 o->u_fun.fun = fun;
1116 return o;
1117}
1118
1119py_obj_t rt_make_function(int n_args, py_fun_t code) {
1120 // assumes code is a pointer to a py_fun_t (i think this is safe...)
1121 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1122 o->kind = O_FUN_N;
Damien429d7192013-10-04 19:53:11 +01001123 o->u_fun.n_args = n_args;
Damien826005c2013-10-05 23:17:28 +01001124 o->u_fun.fun = code;
Damien429d7192013-10-04 19:53:11 +01001125 return o;
1126}
1127
Damieneb19efb2013-10-10 22:06:54 +01001128py_obj_t rt_call_function_0(py_obj_t fun) {
1129 return rt_call_function_n(fun, 0, NULL);
1130}
1131
1132py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) {
1133 return rt_call_function_n(fun, 1, &arg);
1134}
1135
1136py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) {
1137 py_obj_t args[2];
1138 args[1] = arg1;
1139 args[0] = arg2;
1140 return rt_call_function_n(fun, 2, args);
1141}
1142
1143typedef machine_uint_t (*inline_asm_fun_0_t)();
1144typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t);
1145typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t);
1146typedef machine_uint_t (*inline_asm_fun_3_t)(machine_uint_t, machine_uint_t, machine_uint_t);
1147
Damiene4af64f2013-10-06 12:04:13 +01001148// convert a Python object to a sensible value for inline asm
1149machine_uint_t rt_convert_obj_for_inline_asm(py_obj_t obj) {
1150 // TODO for byte_array, pass pointer to the array
1151 if (IS_SMALL_INT(obj)) {
1152 return FROM_SMALL_INT(obj);
1153 } else if (obj == py_const_none) {
1154 return 0;
1155 } else if (obj == py_const_false) {
1156 return 0;
1157 } else if (obj == py_const_true) {
1158 return 1;
1159 } else {
1160 py_obj_base_t *o = obj;
1161 switch (o->kind) {
1162 case O_STR:
1163 // pointer to the string (it's probably constant though!)
1164 return (machine_uint_t)qstr_str(o->u_str);
1165
Damien3ef4abb2013-10-12 16:53:13 +01001166#if MICROPY_ENABLE_FLOAT
Damiene4af64f2013-10-06 12:04:13 +01001167 case O_FLOAT:
1168 // convert float to int (could also pass in float registers)
1169 return (machine_int_t)o->u_flt;
Damienc025ebb2013-10-12 14:30:21 +01001170#endif
Damiene4af64f2013-10-06 12:04:13 +01001171
Damienc226dca2013-10-16 16:12:52 +01001172 case O_TUPLE:
Damiene4af64f2013-10-06 12:04:13 +01001173 case O_LIST:
Damienc226dca2013-10-16 16:12:52 +01001174 // pointer to start of tuple/list (could pass length, but then could use len(x) for that)
1175 return (machine_uint_t)o->u_tuple_list.items;
Damiene4af64f2013-10-06 12:04:13 +01001176
1177 default:
1178 // just pass along a pointer to the object
1179 return (machine_uint_t)obj;
1180 }
1181 }
1182}
1183
1184// convert a return value from inline asm to a sensible Python object
1185py_obj_t rt_convert_val_from_inline_asm(machine_uint_t val) {
1186 return TO_SMALL_INT(val);
1187}
1188
Damieneb19efb2013-10-10 22:06:54 +01001189// args are in reverse order in the array
1190py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args) {
1191 int n_args_fun = 0;
Damien429d7192013-10-04 19:53:11 +01001192 if (IS_O(fun, O_FUN_0)) {
1193 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001194 if (n_args != 0) {
1195 n_args_fun = 0;
1196 goto bad_n_args;
1197 }
1198 DEBUG_OP_printf("calling native %p()\n", o->u_fun.fun);
Damien429d7192013-10-04 19:53:11 +01001199 return ((py_fun_0_t)o->u_fun.fun)();
Damieneb19efb2013-10-10 22:06:54 +01001200
1201 } else if (IS_O(fun, O_FUN_1)) {
1202 py_obj_base_t *o = fun;
1203 if (n_args != 1) {
1204 n_args_fun = 1;
1205 goto bad_n_args;
1206 }
1207 DEBUG_OP_printf("calling native %p(%p)\n", o->u_fun.fun, args[0]);
1208 return ((py_fun_1_t)o->u_fun.fun)(args[0]);
1209
1210 } else if (IS_O(fun, O_FUN_2)) {
1211 py_obj_base_t *o = fun;
1212 if (n_args != 2) {
1213 n_args_fun = 2;
1214 goto bad_n_args;
1215 }
1216 DEBUG_OP_printf("calling native %p(%p, %p)\n", o->u_fun.fun, args[1], args[0]);
1217 return ((py_fun_2_t)o->u_fun.fun)(args[1], args[0]);
1218
1219 // TODO O_FUN_N
1220
Damien429d7192013-10-04 19:53:11 +01001221 } else if (IS_O(fun, O_FUN_BC)) {
1222 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001223 if (n_args != o->u_fun_bc.n_args) {
1224 n_args_fun = o->u_fun_bc.n_args;
1225 goto bad_n_args;
1226 }
1227 DEBUG_OP_printf("calling byte code %p(n_args=%d)\n", o->u_fun_bc.code, n_args);
Damienbd254452013-10-16 20:39:12 +01001228 return py_execute_byte_code(o->u_fun_bc.code, args, n_args);
Damieneb19efb2013-10-10 22:06:54 +01001229
Damiene4af64f2013-10-06 12:04:13 +01001230 } else if (IS_O(fun, O_FUN_ASM)) {
1231 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001232 if (n_args != o->u_fun_asm.n_args) {
1233 n_args_fun = o->u_fun_asm.n_args;
1234 goto bad_n_args;
1235 }
1236 DEBUG_OP_printf("calling inline asm %p(n_args=%d)\n", o->u_fun_asm.fun, n_args);
1237 machine_uint_t ret;
1238 if (n_args == 0) {
1239 ret = ((inline_asm_fun_0_t)o->u_fun_asm.fun)();
1240 } else if (n_args == 1) {
1241 ret = ((inline_asm_fun_1_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[0]));
1242 } else if (n_args == 2) {
1243 ret = ((inline_asm_fun_2_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[1]), rt_convert_obj_for_inline_asm(args[0]));
1244 } else if (n_args == 3) {
1245 ret = ((inline_asm_fun_3_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[2]), rt_convert_obj_for_inline_asm(args[1]), rt_convert_obj_for_inline_asm(args[0]));
1246 } else {
1247 assert(0);
1248 ret = 0;
1249 }
1250 return rt_convert_val_from_inline_asm(ret);
1251
Damienbd254452013-10-16 20:39:12 +01001252 } else if (IS_O(fun, O_GEN_WRAP)) {
1253 py_obj_base_t *o = fun;
1254 py_obj_base_t *o_fun = o->u_gen_wrap.fun;
1255 assert(o_fun->kind == O_FUN_BC); // TODO
1256 if (n_args != o_fun->u_fun_bc.n_args) {
1257 n_args_fun = o_fun->u_fun_bc.n_args;
1258 goto bad_n_args;
1259 }
1260 py_obj_t *state = m_new(py_obj_t, 1 + o->u_gen_wrap.n_state);
1261 // put function object at first slot in state (to keep u_gen_instance small)
1262 state[0] = o_fun;
1263 // init args
1264 for (int i = 0; i < n_args; i++) {
1265 state[1 + i] = args[n_args - 1 - i];
1266 }
1267 py_obj_base_t *o2 = m_new(py_obj_base_t, 1);
1268 o2->kind = O_GEN_INSTANCE;
1269 o2->u_gen_instance.state = state;
1270 o2->u_gen_instance.ip = o_fun->u_fun_bc.code;
1271 o2->u_gen_instance.sp = state + o->u_gen_wrap.n_state;
1272 return o2;
1273
Damiena3977762013-10-09 23:10:10 +01001274 } else if (IS_O(fun, O_BOUND_METH)) {
1275 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001276 DEBUG_OP_printf("calling bound method %p(self=%p, n_args=%d)\n", o->u_bound_meth.meth, o->u_bound_meth.self, n_args);
1277 if (n_args == 0) {
1278 return rt_call_function_n(o->u_bound_meth.meth, 1, &o->u_bound_meth.self);
1279 } else if (n_args == 1) {
1280 py_obj_t args2[2];
1281 args2[1] = o->u_bound_meth.self;
1282 args2[0] = args[0];
1283 return rt_call_function_n(o->u_bound_meth.meth, 2, args2);
1284 } else {
1285 // TODO not implemented
1286 assert(0);
1287 return py_const_none;
1288 //return rt_call_function_2(o->u_bound_meth.meth, n_args + 1, o->u_bound_meth.self + args);
1289 }
1290
Damiena3977762013-10-09 23:10:10 +01001291 } else if (IS_O(fun, O_CLASS)) {
1292 // instantiate an instance of a class
Damieneb19efb2013-10-10 22:06:54 +01001293 if (n_args != 0) {
1294 n_args_fun = 0;
1295 goto bad_n_args;
1296 }
Damiena3977762013-10-09 23:10:10 +01001297 DEBUG_OP_printf("instantiate object of class %p with no args\n", fun);
1298 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1299 o->kind = O_OBJ;
1300 o->u_obj.class = fun;
1301 o->u_obj.members = py_map_new(MAP_QSTR, 0);
1302 return o;
Damieneb19efb2013-10-10 22:06:54 +01001303
Damien429d7192013-10-04 19:53:11 +01001304 } else {
Damieneb19efb2013-10-10 22:06:54 +01001305 printf("fun %p %d\n", fun, ((py_obj_base_t*)fun)->kind);
Damien429d7192013-10-04 19:53:11 +01001306 assert(0);
1307 return py_const_none;
1308 }
Damien429d7192013-10-04 19:53:11 +01001309
Damieneb19efb2013-10-10 22:06:54 +01001310bad_n_args:
Damienbd254452013-10-16 20:39:12 +01001311 nlr_jump(py_obj_new_exception_2(q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)n_args_fun, (const char*)(machine_int_t)n_args));
Damien429d7192013-10-04 19:53:11 +01001312}
1313
Damiena3977762013-10-09 23:10:10 +01001314// args contains: arg(n_args-1) arg(n_args-2) ... arg(0) self/NULL fun
1315// if n_args==0 then there are only self/NULL and fun
1316py_obj_t rt_call_method_n(int n_args, const py_obj_t *args) {
Damien7f5dacf2013-10-10 11:24:39 +01001317 DEBUG_OP_printf("call method %p(self=%p, n_args=%d)\n", args[n_args + 1], args[n_args], n_args);
Damiena3977762013-10-09 23:10:10 +01001318 return rt_call_function_n(args[n_args + 1], n_args + ((args[n_args] == NULL) ? 0 : 1), args);
1319}
1320
Damien429d7192013-10-04 19:53:11 +01001321// items are in reverse order
Damienc226dca2013-10-16 16:12:52 +01001322py_obj_t rt_build_tuple(int n_args, py_obj_t *items) {
1323 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1324 o->kind = O_TUPLE;
1325 o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args;
1326 o->u_tuple_list.len = n_args;
1327 o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc);
1328 for (int i = 0; i < n_args; i++) {
1329 o->u_tuple_list.items[i] = items[n_args - i - 1];
1330 }
1331 return o;
1332}
1333
1334// items are in reverse order
Damien429d7192013-10-04 19:53:11 +01001335py_obj_t rt_build_list(int n_args, py_obj_t *items) {
1336 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1337 o->kind = O_LIST;
Damienc226dca2013-10-16 16:12:52 +01001338 o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args;
1339 o->u_tuple_list.len = n_args;
1340 o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc);
Damien429d7192013-10-04 19:53:11 +01001341 for (int i = 0; i < n_args; i++) {
Damienc226dca2013-10-16 16:12:52 +01001342 o->u_tuple_list.items[i] = items[n_args - i - 1];
Damien429d7192013-10-04 19:53:11 +01001343 }
1344 return o;
1345}
1346
1347py_obj_t py_set_lookup(py_obj_t o_in, py_obj_t index, bool add_if_not_found) {
1348 assert(IS_O(o_in, O_SET));
1349 py_obj_base_t *o = o_in;
1350 int hash = py_obj_hash(index);
1351 int pos = hash % o->u_set.alloc;
1352 for (;;) {
1353 py_obj_t elem = o->u_set.table[pos];
1354 if (elem == NULL) {
1355 // not in table
1356 if (add_if_not_found) {
1357 if (o->u_set.used + 1 >= o->u_set.alloc) {
1358 // not enough room in table, rehash it
1359 int old_alloc = o->u_set.alloc;
1360 py_obj_t *old_table = o->u_set.table;
1361 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(o->u_set.alloc + 1);
1362 o->u_set.used = 0;
1363 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
1364 for (int i = 0; i < old_alloc; i++) {
1365 if (old_table[i] != NULL) {
1366 py_set_lookup(o, old_table[i], true);
1367 }
1368 }
1369 m_free(old_table);
1370 // restart the search for the new element
1371 pos = hash % o->u_set.alloc;
1372 } else {
1373 o->u_set.used += 1;
1374 o->u_set.table[pos] = index;
1375 return index;
1376 }
1377 } else {
1378 return NULL;
1379 }
1380 } else if (py_obj_equal(elem, index)) {
1381 // found it
1382 return elem;
1383 } else {
1384 // not yet found, keep searching in this table
1385 pos = (pos + 1) % o->u_set.alloc;
1386 }
1387 }
1388}
1389
1390py_obj_t rt_build_set(int n_args, py_obj_t *items) {
1391 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1392 o->kind = O_SET;
1393 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(n_args + 1);
1394 o->u_set.used = 0;
1395 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
1396 for (int i = 0; i < o->u_set.alloc; i++) {
1397 o->u_set.table[i] = NULL;
1398 }
1399 for (int i = 0; i < n_args; i++) {
1400 py_set_lookup(o, items[i], true);
1401 }
1402 return o;
1403}
1404
Damienc12aa462013-10-16 20:57:49 +01001405py_obj_t rt_store_set(py_obj_t set, py_obj_t item) {
1406 py_set_lookup(set, item, true);
1407 return set;
1408}
1409
Damien429d7192013-10-04 19:53:11 +01001410py_obj_t rt_build_map(int n_args) {
1411 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1412 o->kind = O_MAP;
1413 py_map_init(&o->u_map, MAP_PY_OBJ, n_args);
1414 return o;
1415}
1416
1417py_obj_t rt_store_map(py_obj_t map, py_obj_t key, py_obj_t value) {
1418 assert(IS_O(map, O_MAP)); // should always be
1419 py_map_lookup(map, key, true)->value = value;
1420 return map;
1421}
1422
Damiena3977762013-10-09 23:10:10 +01001423py_obj_t build_bound_method(py_obj_t self, py_obj_t meth) {
1424 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1425 o->kind = O_BOUND_METH;
1426 o->u_bound_meth.meth = meth;
1427 o->u_bound_meth.self = self;
1428 return o;
1429}
1430
1431py_obj_t rt_load_attr(py_obj_t base, qstr attr) {
1432 DEBUG_OP_printf("load attr %s\n", qstr_str(attr));
1433 if (IS_O(base, O_LIST) && attr == q_append) {
1434 return build_bound_method(base, fun_list_append);
1435 } else if (IS_O(base, O_CLASS)) {
1436 py_obj_base_t *o = base;
1437 py_map_elem_t *elem = py_qstr_map_lookup(o->u_class.locals, attr, false);
1438 if (elem == NULL) {
1439 goto no_attr;
1440 }
1441 return elem->value;
1442 } else if (IS_O(base, O_OBJ)) {
1443 // logic: look in obj members then class locals (TODO check this against CPython)
1444 py_obj_base_t *o = base;
1445 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false);
1446 if (elem != NULL) {
1447 // object member, always treated as a value
1448 return elem->value;
1449 }
1450 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1451 if (elem != NULL) {
1452 if (py_obj_is_callable(elem->value)) {
1453 // class member is callable so build a bound method
1454 return build_bound_method(base, elem->value);
1455 } else {
1456 // class member is a value, so just return that value
1457 return elem->value;
1458 }
1459 }
1460 goto no_attr;
1461 }
1462
1463no_attr:
Damience89a212013-10-15 22:25:17 +01001464 nlr_jump(py_obj_new_exception_2(q_AttributeError, "'%s' object has no attribute '%s'", py_obj_get_type_str(base), qstr_str(attr)));
Damiena3977762013-10-09 23:10:10 +01001465}
1466
1467void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest) {
1468 DEBUG_OP_printf("load method %s\n", qstr_str(attr));
Damienbd254452013-10-16 20:39:12 +01001469 if (IS_O(base, O_GEN_INSTANCE) && attr == q___next__) {
1470 dest[1] = fun_gen_instance_next;
1471 dest[0] = base;
1472 return;
1473 } else if (IS_O(base, O_LIST) && attr == q_append) {
Damiena3977762013-10-09 23:10:10 +01001474 dest[1] = fun_list_append;
1475 dest[0] = base;
1476 return;
1477 } else if (IS_O(base, O_OBJ)) {
1478 // logic: look in obj members then class locals (TODO check this against CPython)
1479 py_obj_base_t *o = base;
1480 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false);
1481 if (elem != NULL) {
1482 // object member, always treated as a value
1483 dest[1] = elem->value;
1484 dest[0] = NULL;
1485 return;
1486 }
1487 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1488 if (elem != NULL) {
1489 if (py_obj_is_callable(elem->value)) {
1490 // class member is callable so build a bound method
1491 dest[1] = elem->value;
1492 dest[0] = base;
1493 return;
1494 } else {
1495 // class member is a value, so just return that value
1496 dest[1] = elem->value;
1497 dest[0] = NULL;
1498 return;
1499 }
1500 }
1501 goto no_attr;
1502 }
1503
1504no_attr:
1505 dest[1] = rt_load_attr(base, attr);
1506 dest[0] = NULL;
1507}
1508
Damien5ac1b2e2013-10-18 19:58:12 +01001509void rt_store_attr(py_obj_t base, qstr attr, py_obj_t value) {
1510 DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value);
Damienec63cce2013-10-22 22:58:17 +01001511 if (IS_O(base, O_CLASS)) {
1512 // TODO CPython allows STORE_ATTR to a class, but is this the correct implementation?
1513 py_obj_base_t *o = base;
1514 py_qstr_map_lookup(o->u_class.locals, attr, true)->value = value;
1515 } else if (IS_O(base, O_OBJ)) {
Damiena3977762013-10-09 23:10:10 +01001516 // logic: look in class locals (no add) then obj members (add) (TODO check this against CPython)
1517 py_obj_base_t *o = base;
1518 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1519 if (elem != NULL) {
Damien5ac1b2e2013-10-18 19:58:12 +01001520 elem->value = value;
Damiena3977762013-10-09 23:10:10 +01001521 } else {
Damienec63cce2013-10-22 22:58:17 +01001522 py_qstr_map_lookup(o->u_obj.members, attr, true)->value = value;
Damiena3977762013-10-09 23:10:10 +01001523 }
1524 } else {
1525 printf("?AttributeError: '%s' object has no attribute '%s'\n", py_obj_get_type_str(base), qstr_str(attr));
1526 assert(0);
1527 }
1528}
1529
Damien429d7192013-10-04 19:53:11 +01001530void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t value) {
Damien5ac1b2e2013-10-18 19:58:12 +01001531 DEBUG_OP_printf("store subscr %p[%p] <- %p\n", base, index, value);
Damienc226dca2013-10-16 16:12:52 +01001532 if (IS_O(base, O_LIST)) {
Damien429d7192013-10-04 19:53:11 +01001533 // list store
Damienc226dca2013-10-16 16:12:52 +01001534 uint i = get_index(base, index);
1535 ((py_obj_base_t*)base)->u_tuple_list.items[i] = value;
Damien429d7192013-10-04 19:53:11 +01001536 } else if (IS_O(base, O_MAP)) {
1537 // map store
1538 py_map_lookup(base, index, true)->value = value;
1539 } else {
1540 assert(0);
1541 }
1542}
1543
Damience89a212013-10-15 22:25:17 +01001544py_obj_t rt_getiter(py_obj_t o_in) {
Damienbd254452013-10-16 20:39:12 +01001545 if (IS_O(o_in, O_GEN_INSTANCE)) {
1546 return o_in;
1547 } else if (IS_O(o_in, O_RANGE)) {
Damience89a212013-10-15 22:25:17 +01001548 py_obj_base_t *o = o_in;
1549 return py_obj_new_range_iterator(o->u_range.start, o->u_range.stop, o->u_range.step);
Damienc226dca2013-10-16 16:12:52 +01001550 } else if (IS_O(o_in, O_TUPLE)) {
1551 return py_obj_new_tuple_iterator(o_in, 0);
1552 } else if (IS_O(o_in, O_LIST)) {
1553 return py_obj_new_list_iterator(o_in, 0);
Damience89a212013-10-15 22:25:17 +01001554 } else {
1555 nlr_jump(py_obj_new_exception_2(q_TypeError, "'%s' object is not iterable", py_obj_get_type_str(o_in), NULL));
1556 }
1557}
1558
1559py_obj_t rt_iternext(py_obj_t o_in) {
Damienbd254452013-10-16 20:39:12 +01001560 if (IS_O(o_in, O_GEN_INSTANCE)) {
1561 py_obj_base_t *self = o_in;
1562 py_obj_base_t *fun = self->u_gen_instance.state[0];
1563 assert(fun->kind == O_FUN_BC);
1564 bool yield = py_execute_byte_code_2(fun->u_fun_bc.code, &self->u_gen_instance.ip, &self->u_gen_instance.state[1], &self->u_gen_instance.sp);
1565 if (yield) {
1566 return *self->u_gen_instance.sp;
1567 } else {
1568 if (*self->u_gen_instance.sp == py_const_none) {
1569 return py_const_stop_iteration;
1570 } else {
1571 // TODO return StopIteration with value *self->u_gen_instance.sp
1572 return py_const_stop_iteration;
1573 }
1574 }
1575
1576 } else if (IS_O(o_in, O_RANGE_IT)) {
Damience89a212013-10-15 22:25:17 +01001577 py_obj_base_t *o = o_in;
1578 if ((o->u_range_it.step > 0 && o->u_range_it.cur < o->u_range_it.stop) || (o->u_range_it.step < 0 && o->u_range_it.cur > o->u_range_it.stop)) {
1579 py_obj_t o_out = TO_SMALL_INT(o->u_range_it.cur);
1580 o->u_range_it.cur += o->u_range_it.step;
1581 return o_out;
1582 } else {
1583 return py_const_stop_iteration;
1584 }
Damienbd254452013-10-16 20:39:12 +01001585
Damienc226dca2013-10-16 16:12:52 +01001586 } else if (IS_O(o_in, O_TUPLE_IT) || IS_O(o_in, O_LIST_IT)) {
1587 py_obj_base_t *o = o_in;
1588 if (o->u_tuple_list_it.cur < o->u_tuple_list_it.obj->u_tuple_list.len) {
1589 py_obj_t o_out = o->u_tuple_list_it.obj->u_tuple_list.items[o->u_tuple_list_it.cur];
1590 o->u_tuple_list_it.cur += 1;
1591 return o_out;
1592 } else {
1593 return py_const_stop_iteration;
1594 }
Damienbd254452013-10-16 20:39:12 +01001595
Damience89a212013-10-15 22:25:17 +01001596 } else {
1597 nlr_jump(py_obj_new_exception_2(q_TypeError, "? '%s' object is not iterable", py_obj_get_type_str(o_in), NULL));
1598 }
1599}
1600
Damiendf4b4f32013-10-19 18:28:01 +01001601void *const rt_fun_table[RT_F_NUMBER_OF] = {
Damien429d7192013-10-04 19:53:11 +01001602 rt_load_const_str,
1603 rt_load_name,
1604 rt_load_global,
Damien7f5dacf2013-10-10 11:24:39 +01001605 rt_load_build_class,
Damien429d7192013-10-04 19:53:11 +01001606 rt_load_attr,
1607 rt_load_method,
1608 rt_store_name,
Damien7f5dacf2013-10-10 11:24:39 +01001609 rt_store_attr,
Damien429d7192013-10-04 19:53:11 +01001610 rt_store_subscr,
1611 rt_is_true,
1612 rt_unary_op,
Damiend2755ec2013-10-16 23:58:48 +01001613 rt_build_tuple,
Damien429d7192013-10-04 19:53:11 +01001614 rt_build_list,
Damiend2755ec2013-10-16 23:58:48 +01001615 rt_list_append,
Damien429d7192013-10-04 19:53:11 +01001616 rt_build_map,
1617 rt_store_map,
1618 rt_build_set,
Damiend2755ec2013-10-16 23:58:48 +01001619 rt_store_set,
Damien429d7192013-10-04 19:53:11 +01001620 rt_make_function_from_id,
Damieneb19efb2013-10-10 22:06:54 +01001621 rt_call_function_n,
Damien7f5dacf2013-10-10 11:24:39 +01001622 rt_call_method_n,
Damien429d7192013-10-04 19:53:11 +01001623 rt_binary_op,
1624 rt_compare_op,
Damiend2755ec2013-10-16 23:58:48 +01001625 rt_getiter,
1626 rt_iternext,
Damien429d7192013-10-04 19:53:11 +01001627};
1628
1629/*
1630void rt_f_vector(rt_fun_kind_t fun_kind) {
1631 (rt_f_table[fun_kind])();
1632}
1633*/
Damienec63cce2013-10-22 22:58:17 +01001634
1635// temporary way of making C modules
1636// hack: use class to mimic a module
1637
Damien8b3a7c22013-10-23 20:20:17 +01001638py_obj_t py_module_new(void) {
Damienec63cce2013-10-22 22:58:17 +01001639 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1640 o->kind = O_CLASS;
1641 o->u_class.locals = py_map_new(MAP_QSTR, 0);
1642 return o;
1643}