blob: 6270039597121820f1fcefeb5abd197a766dc4e0 [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
Damien7410e442013-11-02 19:47:57 +000017#if MICROPY_ENABLE_FLOAT
18// for sqrt
19#include <math.h>
20#endif
21
Damien7f5dacf2013-10-10 11:24:39 +010022#if 0 // print debugging info
Damiena1ddfcc2013-10-10 23:25:50 +010023#define DEBUG_PRINT (1)
24#define WRITE_NATIVE (1)
Damien7f5dacf2013-10-10 11:24:39 +010025#define DEBUG_printf(args...) printf(args)
26#define DEBUG_OP_printf(args...) printf(args)
27#else // don't print debugging info
Damiena3977762013-10-09 23:10:10 +010028#define DEBUG_printf(args...) (void)0
Damien429d7192013-10-04 19:53:11 +010029#define DEBUG_OP_printf(args...) (void)0
Damien7f5dacf2013-10-10 11:24:39 +010030#endif
Damien429d7192013-10-04 19:53:11 +010031
Damien429d7192013-10-04 19:53:11 +010032typedef machine_int_t py_small_int_t;
33
34#define IS_O(o, k) (((((py_small_int_t)(o)) & 1) == 0) && (((py_obj_base_t*)(o))->kind == (k)))
35#define IS_SMALL_INT(o) (((py_small_int_t)(o)) & 1)
36#define FROM_SMALL_INT(o) (((py_small_int_t)(o)) >> 1)
37#define TO_SMALL_INT(o) ((py_obj_t)(((o) << 1) | 1))
38
Damien3ef4abb2013-10-12 16:53:13 +010039#if MICROPY_ENABLE_FLOAT
Damien7410e442013-11-02 19:47:57 +000040typedef machine_float_t py_float_t;
Damien429d7192013-10-04 19:53:11 +010041#endif
42
43typedef enum {
44 O_CONST,
45 O_STR,
Damien3ef4abb2013-10-12 16:53:13 +010046#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +010047 O_FLOAT,
Damien7410e442013-11-02 19:47:57 +000048 O_COMPLEX,
Damien429d7192013-10-04 19:53:11 +010049#endif
Damience89a212013-10-15 22:25:17 +010050 O_EXCEPTION_0,
Damienf086ecf2013-10-22 16:05:11 +010051 O_EXCEPTION_N,
Damience89a212013-10-15 22:25:17 +010052 O_RANGE,
53 O_RANGE_IT,
Damien429d7192013-10-04 19:53:11 +010054 O_FUN_0,
55 O_FUN_1,
56 O_FUN_2,
57 O_FUN_N,
58 O_FUN_BC,
Damien826005c2013-10-05 23:17:28 +010059 O_FUN_ASM,
Damienbd254452013-10-16 20:39:12 +010060 O_GEN_WRAP,
61 O_GEN_INSTANCE,
Damien429d7192013-10-04 19:53:11 +010062 O_BOUND_METH,
Damienc226dca2013-10-16 16:12:52 +010063 O_TUPLE,
Damien429d7192013-10-04 19:53:11 +010064 O_LIST,
Damienc226dca2013-10-16 16:12:52 +010065 O_TUPLE_IT,
66 O_LIST_IT,
Damien429d7192013-10-04 19:53:11 +010067 O_SET,
68 O_MAP,
69 O_CLASS,
Damiena3977762013-10-09 23:10:10 +010070 O_OBJ,
Damien429d7192013-10-04 19:53:11 +010071} py_obj_kind_t;
72
73typedef enum {
74 MAP_QSTR,
75 MAP_PY_OBJ,
76} py_map_kind_t;
77
78typedef struct _py_map_elem_t {
79 py_obj_t key;
80 py_obj_t value;
81} py_map_elem_t;
82
83typedef struct _py_map_t {
Damienf086ecf2013-10-22 16:05:11 +010084 struct {
85 py_map_kind_t kind : 1;
86 machine_uint_t used : (8 * BYTES_PER_WORD - 1);
87 };
Damien429d7192013-10-04 19:53:11 +010088 machine_uint_t alloc;
Damien429d7192013-10-04 19:53:11 +010089 py_map_elem_t *table;
90} py_map_t;
91
Damiena3977762013-10-09 23:10:10 +010092typedef struct _py_obj_base_t py_obj_base_t;
93
94struct _py_obj_base_t {
Damien429d7192013-10-04 19:53:11 +010095 py_obj_kind_t kind;
96 union {
97 const char *id;
98 qstr u_str;
Damien3ef4abb2013-10-12 16:53:13 +010099#if MICROPY_ENABLE_FLOAT
Damien7410e442013-11-02 19:47:57 +0000100 py_float_t u_float; // for O_FLOAT
101 struct { // for O_COMPLEX
102 py_float_t real;
103 py_float_t imag;
104 } u_complex;
Damien429d7192013-10-04 19:53:11 +0100105#endif
Damience89a212013-10-15 22:25:17 +0100106 struct { // for O_EXCEPTION_0
107 qstr id;
108 } u_exc0;
Damienf086ecf2013-10-22 16:05:11 +0100109 struct { // for O_EXCEPTION_N
110 // TODO make generic object or something
Damience89a212013-10-15 22:25:17 +0100111 qstr id;
Damienf086ecf2013-10-22 16:05:11 +0100112 int n_args;
113 const void **args;
114 } u_exc_n;
Damience89a212013-10-15 22:25:17 +0100115 struct { // for O_RANGE
116 // TODO make generic object or something
117 machine_int_t start;
118 machine_int_t stop;
119 machine_int_t step;
120 } u_range;
121 struct { // for O_RANGE_IT
122 // TODO make generic object or something
123 machine_int_t cur;
124 machine_int_t stop;
125 machine_int_t step;
126 } u_range_it;
Damien429d7192013-10-04 19:53:11 +0100127 struct { // for O_FUN_[012N]
Damien429d7192013-10-04 19:53:11 +0100128 int n_args;
Damien826005c2013-10-05 23:17:28 +0100129 void *fun;
Damien429d7192013-10-04 19:53:11 +0100130 } u_fun;
131 struct { // for O_FUN_BC
Damien826005c2013-10-05 23:17:28 +0100132 int n_args;
Damien429d7192013-10-04 19:53:11 +0100133 byte *code;
134 uint len;
Damien429d7192013-10-04 19:53:11 +0100135 } u_fun_bc;
Damien826005c2013-10-05 23:17:28 +0100136 struct { // for O_FUN_ASM
137 int n_args;
138 void *fun;
139 } u_fun_asm;
Damienbd254452013-10-16 20:39:12 +0100140 struct { // for O_GEN_WRAP
141 int n_state;
142 py_obj_base_t *fun;
143 } u_gen_wrap;
144 struct { // for O_GEN_INSTANCE
145 py_obj_t *state;
146 const byte *ip;
147 py_obj_t *sp;
148 } u_gen_instance;
Damien429d7192013-10-04 19:53:11 +0100149 struct { // for O_BOUND_METH
150 py_obj_t meth;
151 py_obj_t self;
152 } u_bound_meth;
Damienc226dca2013-10-16 16:12:52 +0100153 struct { // for O_TUPLE, O_LIST
Damienf086ecf2013-10-22 16:05:11 +0100154 machine_uint_t alloc;
155 machine_uint_t len;
Damien429d7192013-10-04 19:53:11 +0100156 py_obj_t *items;
Damienc226dca2013-10-16 16:12:52 +0100157 } u_tuple_list;
158 struct { // for O_TUPLE_IT, O_LIST_IT
159 py_obj_base_t *obj;
Damienf086ecf2013-10-22 16:05:11 +0100160 machine_uint_t cur;
Damienc226dca2013-10-16 16:12:52 +0100161 } u_tuple_list_it;
Damien429d7192013-10-04 19:53:11 +0100162 struct { // for O_SET
Damienf086ecf2013-10-22 16:05:11 +0100163 machine_uint_t alloc;
164 machine_uint_t used;
Damien429d7192013-10-04 19:53:11 +0100165 py_obj_t *table;
166 } u_set;
167 py_map_t u_map; // for O_MAP
Damien429d7192013-10-04 19:53:11 +0100168 struct { // for O_CLASS
Damiena3977762013-10-09 23:10:10 +0100169 py_map_t *locals;
Damien429d7192013-10-04 19:53:11 +0100170 } u_class;
Damiena3977762013-10-09 23:10:10 +0100171 struct { // for O_OBJ
172 py_obj_base_t *class; // points to a O_CLASS object
173 py_map_t *members;
174 } u_obj;
Damien429d7192013-10-04 19:53:11 +0100175 };
Damiena3977762013-10-09 23:10:10 +0100176};
Damien429d7192013-10-04 19:53:11 +0100177
Damien4ebb32f2013-11-02 14:33:10 +0000178static qstr q_append;
179static qstr q_join;
180static qstr q_print;
181static qstr q_len;
182static qstr q___build_class__;
183static qstr q___next__;
184static qstr q_AttributeError;
185static qstr q_IndexError;
186static qstr q_KeyError;
187static qstr q_NameError;
188static qstr q_TypeError;
Damien7410e442013-11-02 19:47:57 +0000189static qstr q_SyntaxError;
Damien4ebb32f2013-11-02 14:33:10 +0000190
Damien429d7192013-10-04 19:53:11 +0100191py_obj_t py_const_none;
192py_obj_t py_const_false;
193py_obj_t py_const_true;
Damience89a212013-10-15 22:25:17 +0100194py_obj_t py_const_stop_iteration;
Damien429d7192013-10-04 19:53:11 +0100195
Damieneb19efb2013-10-10 22:06:54 +0100196// locals and globals need to be pointers because they can be the same in outer module scope
Damien4ebb32f2013-11-02 14:33:10 +0000197static py_map_t *map_locals;
198static py_map_t *map_globals;
199static py_map_t map_builtins;
Damien429d7192013-10-04 19:53:11 +0100200
201// approximatelly doubling primes; made with Mathematica command: Table[Prime[Floor[(1.7)^n]], {n, 3, 24}]
202static 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};
203
204int get_doubling_prime_greater_or_equal_to(int x) {
205 for (int i = 0; i < sizeof(doubling_primes) / sizeof(int); i++) {
206 if (doubling_primes[i] >= x) {
207 return doubling_primes[i];
208 }
209 }
210 // ran out of primes in the table!
211 // return something sensible, at least make it odd
212 return x | 1;
213}
214
215void py_map_init(py_map_t *map, py_map_kind_t kind, int n) {
216 map->kind = kind;
Damien429d7192013-10-04 19:53:11 +0100217 map->used = 0;
Damienf086ecf2013-10-22 16:05:11 +0100218 map->alloc = get_doubling_prime_greater_or_equal_to(n + 1);
Damien5ac1b2e2013-10-18 19:58:12 +0100219 map->table = m_new0(py_map_elem_t, map->alloc);
Damien429d7192013-10-04 19:53:11 +0100220}
221
222py_map_t *py_map_new(py_map_kind_t kind, int n) {
223 py_map_t *map = m_new(py_map_t, 1);
224 py_map_init(map, kind, n);
225 return map;
226}
227
Damien5ac1b2e2013-10-18 19:58:12 +0100228machine_int_t py_obj_hash(py_obj_t o_in) {
229 if (o_in == py_const_false) {
230 return 0; // needs to hash to same as the integer 0, since False==0
231 } else if (o_in == py_const_true) {
232 return 1; // needs to hash to same as the integer 1, since True==1
233 } else if (IS_SMALL_INT(o_in)) {
Damien429d7192013-10-04 19:53:11 +0100234 return FROM_SMALL_INT(o_in);
Damien5ac1b2e2013-10-18 19:58:12 +0100235 } else if (IS_O(o_in, O_CONST)) {
236 return (machine_int_t)o_in;
Damien429d7192013-10-04 19:53:11 +0100237 } else if (IS_O(o_in, O_STR)) {
238 return ((py_obj_base_t*)o_in)->u_str;
239 } else {
240 assert(0);
241 return 0;
242 }
243}
244
Damien5ac1b2e2013-10-18 19:58:12 +0100245// this function implements the '==' operator (and so the inverse of '!=')
246// from the python language reference:
247// "The objects need not have the same type. If both are numbers, they are converted
248// to a common type. Otherwise, the == and != operators always consider objects of
249// different types to be unequal."
250// note also that False==0 and True==1 are true expressions
Damien429d7192013-10-04 19:53:11 +0100251bool py_obj_equal(py_obj_t o1, py_obj_t o2) {
252 if (o1 == o2) {
253 return true;
Damien5ac1b2e2013-10-18 19:58:12 +0100254 } else if (IS_SMALL_INT(o1) || IS_SMALL_INT(o2)) {
255 if (IS_SMALL_INT(o1) && IS_SMALL_INT(o2)) {
256 return false;
257 } else {
258 if (IS_SMALL_INT(o2)) {
259 py_obj_t temp = o1; o1 = o2; o2 = temp;
260 }
261 // o1 is the SMALL_INT, o2 is not
262 py_small_int_t val = FROM_SMALL_INT(o1);
263 if (o2 == py_const_false) {
264 return val == 0;
265 } else if (o2 == py_const_true) {
266 return val == 1;
267 } else {
268 return false;
269 }
270 }
Damien429d7192013-10-04 19:53:11 +0100271 } else if (IS_O(o1, O_STR) && IS_O(o2, O_STR)) {
272 return ((py_obj_base_t*)o1)->u_str == ((py_obj_base_t*)o2)->u_str;
273 } else {
274 assert(0);
275 return false;
276 }
277}
278
279py_map_elem_t* py_map_lookup_helper(py_map_t *map, py_obj_t index, bool add_if_not_found) {
280 bool is_map_py_obj = (map->kind == MAP_PY_OBJ);
281 machine_uint_t hash;
282 if (is_map_py_obj) {
283 hash = py_obj_hash(index);
284 } else {
285 hash = (machine_uint_t)index;
286 }
287 uint pos = hash % map->alloc;
288 for (;;) {
289 py_map_elem_t *elem = &map->table[pos];
290 if (elem->key == NULL) {
291 // not in table
292 if (add_if_not_found) {
293 if (map->used + 1 >= map->alloc) {
294 // not enough room in table, rehash it
295 int old_alloc = map->alloc;
296 py_map_elem_t *old_table = map->table;
297 map->alloc = get_doubling_prime_greater_or_equal_to(map->alloc + 1);
298 map->used = 0;
Damien5ac1b2e2013-10-18 19:58:12 +0100299 map->table = m_new0(py_map_elem_t, map->alloc);
Damien429d7192013-10-04 19:53:11 +0100300 for (int i = 0; i < old_alloc; i++) {
301 if (old_table[i].key != NULL) {
302 py_map_lookup_helper(map, old_table[i].key, true)->value = old_table[i].value;
303 }
304 }
305 m_free(old_table);
306 // restart the search for the new element
307 pos = hash % map->alloc;
308 } else {
309 map->used += 1;
310 elem->key = index;
311 return elem;
312 }
313 } else {
314 return NULL;
315 }
316 } else if (elem->key == index || (is_map_py_obj && py_obj_equal(elem->key, index))) {
317 // found it
Damien5ac1b2e2013-10-18 19:58:12 +0100318 /* it seems CPython does not replace the index; try x={True:'true'};x[1]='one';x
Damien429d7192013-10-04 19:53:11 +0100319 if (add_if_not_found) {
320 elem->key = index;
321 }
Damien5ac1b2e2013-10-18 19:58:12 +0100322 */
Damien429d7192013-10-04 19:53:11 +0100323 return elem;
324 } else {
325 // not yet found, keep searching in this table
326 pos = (pos + 1) % map->alloc;
327 }
328 }
329}
330
331py_map_elem_t* py_qstr_map_lookup(py_map_t *map, qstr index, bool add_if_not_found) {
332 py_obj_t o = (py_obj_t)(machine_uint_t)index;
333 return py_map_lookup_helper(map, o, add_if_not_found);
334}
335
336py_map_elem_t* py_map_lookup(py_obj_t o, py_obj_t index, bool add_if_not_found) {
337 assert(IS_O(o, O_MAP));
338 return py_map_lookup_helper(&((py_obj_base_t *)o)->u_map, index, add_if_not_found);
339}
340
341static bool fit_small_int(py_small_int_t o) {
342 return true;
343}
344
Damien4ebb32f2013-11-02 14:33:10 +0000345py_obj_t py_obj_new_int(machine_int_t value) {
Damien6f08f8c2013-10-23 22:17:26 +0100346 return TO_SMALL_INT(value);
347}
348
Damien429d7192013-10-04 19:53:11 +0100349py_obj_t py_obj_new_const(const char *id) {
350 py_obj_base_t *o = m_new(py_obj_base_t, 1);
351 o->kind = O_CONST;
352 o->id = id;
353 return (py_obj_t)o;
354}
355
356py_obj_t py_obj_new_str(qstr qstr) {
357 py_obj_base_t *o = m_new(py_obj_base_t, 1);
358 o->kind = O_STR;
359 o->u_str = qstr;
360 return (py_obj_t)o;
361}
362
Damien3ef4abb2013-10-12 16:53:13 +0100363#if MICROPY_ENABLE_FLOAT
Damien7410e442013-11-02 19:47:57 +0000364py_obj_t py_obj_new_float(py_float_t val) {
Damien429d7192013-10-04 19:53:11 +0100365 py_obj_base_t *o = m_new(py_obj_base_t, 1);
366 o->kind = O_FLOAT;
Damien7410e442013-11-02 19:47:57 +0000367 o->u_float = val;
368 return (py_obj_t)o;
369}
370
371py_obj_t py_obj_new_complex(py_float_t real, py_float_t imag) {
372 py_obj_base_t *o = m_new(py_obj_base_t, 1);
373 o->kind = O_COMPLEX;
374 o->u_complex.real = real;
375 o->u_complex.imag = imag;
Damien429d7192013-10-04 19:53:11 +0100376 return (py_obj_t)o;
377}
378#endif
379
Damience89a212013-10-15 22:25:17 +0100380py_obj_t py_obj_new_exception_0(qstr id) {
381 py_obj_base_t *o = m_new(py_obj_base_t, 1);
382 o->kind = O_EXCEPTION_0;
383 o->u_exc0.id = id;
384 return (py_obj_t)o;
385}
386
387py_obj_t py_obj_new_exception_2(qstr id, const char *fmt, const char *s1, const char *s2) {
388 py_obj_base_t *o = m_new(py_obj_base_t, 1);
Damienf086ecf2013-10-22 16:05:11 +0100389 o->kind = O_EXCEPTION_N;
390 o->u_exc_n.id = id;
391 o->u_exc_n.n_args = 3;
392 o->u_exc_n.args = m_new(const void*, 3);
393 o->u_exc_n.args[0] = fmt;
394 o->u_exc_n.args[1] = s1;
395 o->u_exc_n.args[2] = s2;
Damience89a212013-10-15 22:25:17 +0100396 return (py_obj_t)o;
397}
398
399// range is a class and instances are immutable sequence objects
400py_obj_t py_obj_new_range(int start, int stop, int step) {
401 py_obj_base_t *o = m_new(py_obj_base_t, 1);
402 o->kind = O_RANGE;
403 o->u_range.start = start;
404 o->u_range.stop = stop;
405 o->u_range.step = step;
406 return o;
407}
408
409py_obj_t py_obj_new_range_iterator(int cur, int stop, int step) {
410 py_obj_base_t *o = m_new(py_obj_base_t, 1);
411 o->kind = O_RANGE_IT;
412 o->u_range_it.cur = cur;
413 o->u_range_it.stop = stop;
414 o->u_range_it.step = step;
415 return o;
416}
417
Damienc226dca2013-10-16 16:12:52 +0100418py_obj_t py_obj_new_tuple_iterator(py_obj_base_t *tuple, int cur) {
419 py_obj_base_t *o = m_new(py_obj_base_t, 1);
420 o->kind = O_TUPLE_IT;
421 o->u_tuple_list_it.obj = tuple;
422 o->u_tuple_list_it.cur = cur;
423 return o;
424}
425
426py_obj_t py_obj_new_list_iterator(py_obj_base_t *list, int cur) {
427 py_obj_base_t *o = m_new(py_obj_base_t, 1);
428 o->kind = O_LIST_IT;
429 o->u_tuple_list_it.obj = list;
430 o->u_tuple_list_it.cur = cur;
431 return o;
432}
433
Damien4ebb32f2013-11-02 14:33:10 +0000434py_obj_t rt_str_join(py_obj_t self_in, py_obj_t arg) {
435 assert(IS_O(self_in, O_STR));
436 py_obj_base_t *self = self_in;
437 int required_len = strlen(qstr_str(self->u_str));
438
439 // process arg, count required chars
440 if (!IS_O(arg, O_TUPLE) && !IS_O(arg, O_LIST)) {
441 goto bad_arg;
442 }
443 py_obj_base_t *tuple_list = arg;
444 for (int i = 0; i < tuple_list->u_tuple_list.len; i++) {
445 if (!IS_O(tuple_list->u_tuple_list.items[i], O_STR)) {
446 goto bad_arg;
447 }
448 required_len += strlen(qstr_str(((py_obj_base_t*)tuple_list->u_tuple_list.items[i])->u_str));
449 }
450
451 // make joined string
452 char *joined_str = m_new(char, required_len + 1);
453 joined_str[0] = 0;
454 for (int i = 0; i < tuple_list->u_tuple_list.len; i++) {
455 const char *s2 = qstr_str(((py_obj_base_t*)tuple_list->u_tuple_list.items[i])->u_str);
456 if (i > 0) {
457 strcat(joined_str, qstr_str(self->u_str));
458 }
459 strcat(joined_str, s2);
460 }
461 return py_obj_new_str(qstr_from_str_take(joined_str));
462
463bad_arg:
464 nlr_jump(py_obj_new_exception_2(q_TypeError, "?str.join expecting a list of str's", NULL, NULL));
465}
466
Damienc226dca2013-10-16 16:12:52 +0100467py_obj_t rt_list_append(py_obj_t self_in, py_obj_t arg) {
Damien429d7192013-10-04 19:53:11 +0100468 assert(IS_O(self_in, O_LIST));
469 py_obj_base_t *self = self_in;
Damienc226dca2013-10-16 16:12:52 +0100470 if (self->u_tuple_list.len >= self->u_tuple_list.alloc) {
471 self->u_tuple_list.alloc *= 2;
472 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 +0100473 }
Damienc226dca2013-10-16 16:12:52 +0100474 self->u_tuple_list.items[self->u_tuple_list.len++] = arg;
Damienccfc9c52013-11-02 15:10:37 +0000475 return py_const_none; // return None, as per CPython
Damien429d7192013-10-04 19:53:11 +0100476}
477
Damienbd254452013-10-16 20:39:12 +0100478py_obj_t rt_gen_instance_next(py_obj_t self_in) {
479 py_obj_t ret = rt_iternext(self_in);
480 if (ret == py_const_stop_iteration) {
481 nlr_jump(py_obj_new_exception_0(qstr_from_str_static("StopIteration")));
482 } else {
483 return ret;
484 }
485}
486
Damien429d7192013-10-04 19:53:11 +0100487typedef enum {
Damien826005c2013-10-05 23:17:28 +0100488 PY_CODE_NONE,
Damien429d7192013-10-04 19:53:11 +0100489 PY_CODE_BYTE,
Damien826005c2013-10-05 23:17:28 +0100490 PY_CODE_NATIVE,
491 PY_CODE_INLINE_ASM,
Damien429d7192013-10-04 19:53:11 +0100492} py_code_kind_t;
493
494typedef struct _py_code_t {
495 py_code_kind_t kind;
496 int n_args;
Damienbd254452013-10-16 20:39:12 +0100497 int n_locals;
498 int n_stack;
499 bool is_generator;
Damien429d7192013-10-04 19:53:11 +0100500 union {
501 struct {
Damien429d7192013-10-04 19:53:11 +0100502 byte *code;
503 uint len;
504 } u_byte;
Damien826005c2013-10-05 23:17:28 +0100505 struct {
506 py_fun_t fun;
507 } u_native;
508 struct {
Damiene4af64f2013-10-06 12:04:13 +0100509 void *fun;
Damien826005c2013-10-05 23:17:28 +0100510 } u_inline_asm;
Damien429d7192013-10-04 19:53:11 +0100511 };
512} py_code_t;
513
514static int next_unique_code_id;
515static py_code_t *unique_codes;
516
Damien4ebb32f2013-11-02 14:33:10 +0000517py_obj_t fun_str_join;
Damien429d7192013-10-04 19:53:11 +0100518py_obj_t fun_list_append;
Damienbd254452013-10-16 20:39:12 +0100519py_obj_t fun_gen_instance_next;
Damien429d7192013-10-04 19:53:11 +0100520
Damien5ac1b2e2013-10-18 19:58:12 +0100521py_obj_t py_builtin___repl_print__(py_obj_t o) {
522 if (o != py_const_none) {
523 py_obj_print(o);
524 printf("\n");
525 }
526 return py_const_none;
527}
528
Damien429d7192013-10-04 19:53:11 +0100529py_obj_t py_builtin_print(py_obj_t o) {
530 if (IS_O(o, O_STR)) {
531 // special case, print string raw
532 printf("%s\n", qstr_str(((py_obj_base_t*)o)->u_str));
533 } else {
534 // print the object Python style
535 py_obj_print(o);
536 printf("\n");
537 }
538 return py_const_none;
539}
540
541py_obj_t py_builtin_len(py_obj_t o_in) {
542 py_small_int_t len = 0;
Damienc226dca2013-10-16 16:12:52 +0100543 if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) {
Damien429d7192013-10-04 19:53:11 +0100544 py_obj_base_t *o = o_in;
Damienc226dca2013-10-16 16:12:52 +0100545 len = o->u_tuple_list.len;
Damien429d7192013-10-04 19:53:11 +0100546 } else if (IS_O(o_in, O_MAP)) {
547 py_obj_base_t *o = o_in;
548 len = o->u_map.used;
549 } else {
550 assert(0);
551 }
552 return TO_SMALL_INT(len);
553}
554
Damien7410e442013-11-02 19:47:57 +0000555py_obj_t py_builtin_abs(py_obj_t o_in) {
556 if (IS_SMALL_INT(o_in)) {
557 py_small_int_t val = FROM_SMALL_INT(o_in);
558 if (val < 0) {
559 val = -val;
560 }
561 return TO_SMALL_INT(val);
562 } else if (IS_O(o_in, O_FLOAT)) {
563 py_obj_base_t *o = o_in;
564 // TODO check for NaN etc
565 if (o->u_float < 0) {
566 return py_obj_new_float(-o->u_float);
567 } else {
568 return o_in;
569 }
570 } else if (IS_O(o_in, O_COMPLEX)) {
571 py_obj_base_t *o = o_in;
572 return py_obj_new_float(sqrt(o->u_complex.real*o->u_complex.real + o->u_complex.imag*o->u_complex.imag));
573 } else {
574 assert(0);
575 return py_const_none;
576 }
577}
578
Damiena3977762013-10-09 23:10:10 +0100579py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name) {
580 // we differ from CPython: we set the new __locals__ object here
Damieneb19efb2013-10-10 22:06:54 +0100581 py_map_t *old_locals = map_locals;
Damiena3977762013-10-09 23:10:10 +0100582 py_map_t *class_locals = py_map_new(MAP_QSTR, 0);
Damieneb19efb2013-10-10 22:06:54 +0100583 map_locals = class_locals;
Damiena3977762013-10-09 23:10:10 +0100584
585 // call the class code
586 rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef);
587
588 // restore old __locals__ object
589 map_locals = old_locals;
590
591 // create and return the new class
Damien429d7192013-10-04 19:53:11 +0100592 py_obj_base_t *o = m_new(py_obj_base_t, 1);
593 o->kind = O_CLASS;
Damiena3977762013-10-09 23:10:10 +0100594 o->u_class.locals = class_locals;
Damien429d7192013-10-04 19:53:11 +0100595 return o;
596}
597
Damience89a212013-10-15 22:25:17 +0100598py_obj_t py_builtin_range(py_obj_t o_arg) {
Damien9fc79332013-10-23 00:01:10 +0100599 return py_obj_new_range(0, py_get_int(o_arg), 1);
Damience89a212013-10-15 22:25:17 +0100600}
601
Damiena1ddfcc2013-10-10 23:25:50 +0100602#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100603FILE *fp_native = NULL;
Damiena1ddfcc2013-10-10 23:25:50 +0100604#endif
Damien429d7192013-10-04 19:53:11 +0100605
Damien8b3a7c22013-10-23 20:20:17 +0100606void rt_init(void) {
Damien429d7192013-10-04 19:53:11 +0100607 q_append = qstr_from_str_static("append");
Damien4ebb32f2013-11-02 14:33:10 +0000608 q_join = qstr_from_str_static("join");
Damien429d7192013-10-04 19:53:11 +0100609 q_print = qstr_from_str_static("print");
610 q_len = qstr_from_str_static("len");
611 q___build_class__ = qstr_from_str_static("__build_class__");
Damienbd254452013-10-16 20:39:12 +0100612 q___next__ = qstr_from_str_static("__next__");
Damience89a212013-10-15 22:25:17 +0100613 q_AttributeError = qstr_from_str_static("AttributeError");
Damienc226dca2013-10-16 16:12:52 +0100614 q_IndexError = qstr_from_str_static("IndexError");
Damien5ac1b2e2013-10-18 19:58:12 +0100615 q_KeyError = qstr_from_str_static("KeyError");
Damience89a212013-10-15 22:25:17 +0100616 q_NameError = qstr_from_str_static("NameError");
617 q_TypeError = qstr_from_str_static("TypeError");
Damien7410e442013-11-02 19:47:57 +0000618 q_SyntaxError = qstr_from_str_static("SyntaxError");
Damien429d7192013-10-04 19:53:11 +0100619
620 py_const_none = py_obj_new_const("None");
621 py_const_false = py_obj_new_const("False");
622 py_const_true = py_obj_new_const("True");
Damience89a212013-10-15 22:25:17 +0100623 py_const_stop_iteration = py_obj_new_const("StopIteration");
Damien429d7192013-10-04 19:53:11 +0100624
Damieneb19efb2013-10-10 22:06:54 +0100625 // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
626 map_locals = map_globals = py_map_new(MAP_QSTR, 1);
627 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 +0100628
629 py_map_init(&map_builtins, MAP_QSTR, 3);
Damien5ac1b2e2013-10-18 19:58:12 +0100630 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 +0100631 py_qstr_map_lookup(&map_builtins, q_print, true)->value = rt_make_function_1(py_builtin_print);
632 py_qstr_map_lookup(&map_builtins, q_len, true)->value = rt_make_function_1(py_builtin_len);
Damien7410e442013-11-02 19:47:57 +0000633 py_qstr_map_lookup(&map_builtins, qstr_from_str_static("abs"), true)->value = rt_make_function_1(py_builtin_abs);
Damien429d7192013-10-04 19:53:11 +0100634 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 +0100635 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 +0100636
Damien5ac1b2e2013-10-18 19:58:12 +0100637 next_unique_code_id = 2; // 1 is reserved for the __main__ module scope
Damien429d7192013-10-04 19:53:11 +0100638 unique_codes = NULL;
639
Damien4ebb32f2013-11-02 14:33:10 +0000640 fun_str_join = rt_make_function_2(rt_str_join);
Damienc226dca2013-10-16 16:12:52 +0100641 fun_list_append = rt_make_function_2(rt_list_append);
Damienbd254452013-10-16 20:39:12 +0100642 fun_gen_instance_next = rt_make_function_1(rt_gen_instance_next);
Damien429d7192013-10-04 19:53:11 +0100643
Damiena1ddfcc2013-10-10 23:25:50 +0100644#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100645 fp_native = fopen("out-native", "wb");
Damiena1ddfcc2013-10-10 23:25:50 +0100646#endif
Damien429d7192013-10-04 19:53:11 +0100647}
648
Damien8b3a7c22013-10-23 20:20:17 +0100649void rt_deinit(void) {
Damiena1ddfcc2013-10-10 23:25:50 +0100650#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100651 if (fp_native != NULL) {
652 fclose(fp_native);
653 }
Damiena1ddfcc2013-10-10 23:25:50 +0100654#endif
Damien429d7192013-10-04 19:53:11 +0100655}
656
Damien5ac1b2e2013-10-18 19:58:12 +0100657int rt_get_unique_code_id(bool is_main_module) {
658 if (is_main_module) {
659 return 1;
660 } else {
661 return next_unique_code_id++;
662 }
Damien429d7192013-10-04 19:53:11 +0100663}
664
Damien8b3a7c22013-10-23 20:20:17 +0100665static void alloc_unique_codes(void) {
Damien429d7192013-10-04 19:53:11 +0100666 if (unique_codes == NULL) {
Damiene0b18642013-11-02 16:41:24 +0000667 unique_codes = m_new(py_code_t, next_unique_code_id + 10); // XXX hack until we fix the REPL allocation problem
Damien826005c2013-10-05 23:17:28 +0100668 for (int i = 0; i < next_unique_code_id; i++) {
669 unique_codes[i].kind = PY_CODE_NONE;
670 }
Damien429d7192013-10-04 19:53:11 +0100671 }
Damien826005c2013-10-05 23:17:28 +0100672}
673
Damienbd254452013-10-16 20:39:12 +0100674void 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 +0100675 alloc_unique_codes();
676
677 assert(unique_code_id < next_unique_code_id);
678 unique_codes[unique_code_id].kind = PY_CODE_BYTE;
679 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +0100680 unique_codes[unique_code_id].n_locals = n_locals;
681 unique_codes[unique_code_id].n_stack = n_stack;
682 unique_codes[unique_code_id].is_generator = is_generator;
Damien826005c2013-10-05 23:17:28 +0100683 unique_codes[unique_code_id].u_byte.code = code;
684 unique_codes[unique_code_id].u_byte.len = len;
685
686 DEBUG_printf("assign byte code: id=%d code=%p len=%u n_args=%d\n", unique_code_id, code, len, n_args);
687}
688
689void rt_assign_native_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
690 alloc_unique_codes();
691
Damienb05d7072013-10-05 13:37:10 +0100692 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
Damien429d7192013-10-04 19:53:11 +0100693 unique_codes[unique_code_id].kind = PY_CODE_NATIVE;
694 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +0100695 unique_codes[unique_code_id].n_locals = 0;
696 unique_codes[unique_code_id].n_stack = 0;
697 unique_codes[unique_code_id].is_generator = false;
Damien429d7192013-10-04 19:53:11 +0100698 unique_codes[unique_code_id].u_native.fun = fun;
699
Damiena1ddfcc2013-10-10 23:25:50 +0100700#ifdef DEBUG_PRINT
Damien429d7192013-10-04 19:53:11 +0100701 DEBUG_printf("assign native code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
702 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
703 for (int i = 0; i < 128 && i < len; i++) {
704 if (i > 0 && i % 16 == 0) {
705 DEBUG_printf("\n");
706 }
707 DEBUG_printf(" %02x", fun_data[i]);
708 }
709 DEBUG_printf("\n");
710
Damiena1ddfcc2013-10-10 23:25:50 +0100711#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100712 if (fp_native != NULL) {
713 fwrite(fun_data, len, 1, fp_native);
Damien13ed3a62013-10-08 09:05:10 +0100714 fflush(fp_native);
Damien429d7192013-10-04 19:53:11 +0100715 }
Damiena1ddfcc2013-10-10 23:25:50 +0100716#endif
717#endif
Damien429d7192013-10-04 19:53:11 +0100718}
719
Damien826005c2013-10-05 23:17:28 +0100720void rt_assign_inline_asm_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
721 alloc_unique_codes();
Damien429d7192013-10-04 19:53:11 +0100722
Damien826005c2013-10-05 23:17:28 +0100723 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
724 unique_codes[unique_code_id].kind = PY_CODE_INLINE_ASM;
725 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +0100726 unique_codes[unique_code_id].n_locals = 0;
727 unique_codes[unique_code_id].n_stack = 0;
728 unique_codes[unique_code_id].is_generator = false;
Damien826005c2013-10-05 23:17:28 +0100729 unique_codes[unique_code_id].u_inline_asm.fun = fun;
730
Damiena1ddfcc2013-10-10 23:25:50 +0100731#ifdef DEBUG_PRINT
Damien826005c2013-10-05 23:17:28 +0100732 DEBUG_printf("assign inline asm code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
733 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
734 for (int i = 0; i < 128 && i < len; i++) {
735 if (i > 0 && i % 16 == 0) {
736 DEBUG_printf("\n");
737 }
738 DEBUG_printf(" %02x", fun_data[i]);
739 }
740 DEBUG_printf("\n");
741
Damiena1ddfcc2013-10-10 23:25:50 +0100742#ifdef WRITE_NATIVE
Damien826005c2013-10-05 23:17:28 +0100743 if (fp_native != NULL) {
744 fwrite(fun_data, len, 1, fp_native);
745 }
Damiena1ddfcc2013-10-10 23:25:50 +0100746#endif
747#endif
Damien429d7192013-10-04 19:53:11 +0100748}
749
Damiena3977762013-10-09 23:10:10 +0100750bool py_obj_is_callable(py_obj_t o_in) {
751 if (IS_SMALL_INT(o_in)) {
752 return false;
753 } else {
754 py_obj_base_t *o = o_in;
755 switch (o->kind) {
756 case O_FUN_0:
757 case O_FUN_1:
758 case O_FUN_2:
759 case O_FUN_N:
760 case O_FUN_BC:
761 case O_FUN_ASM:
Damieneb19efb2013-10-10 22:06:54 +0100762 // what about O_CLASS, and an O_OBJ that has a __call__ method?
Damiena3977762013-10-09 23:10:10 +0100763 return true;
764 default:
765 return false;
766 }
767 }
768}
769
Damien429d7192013-10-04 19:53:11 +0100770const char *py_obj_get_type_str(py_obj_t o_in) {
771 if (IS_SMALL_INT(o_in)) {
772 return "int";
773 } else {
774 py_obj_base_t *o = o_in;
775 switch (o->kind) {
776 case O_CONST:
777 if (o == py_const_none) {
778 return "NoneType";
779 } else {
780 return "bool";
781 }
782 case O_STR:
783 return "str";
Damien3ef4abb2013-10-12 16:53:13 +0100784#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100785 case O_FLOAT:
786 return "float";
787#endif
Damien6cdd3af2013-10-05 18:08:26 +0100788 case O_FUN_0:
789 case O_FUN_1:
790 case O_FUN_2:
791 case O_FUN_N:
792 case O_FUN_BC:
793 return "function";
Damienbd254452013-10-16 20:39:12 +0100794 case O_GEN_INSTANCE:
795 return "generator";
Damienc226dca2013-10-16 16:12:52 +0100796 case O_TUPLE:
797 return "tuple";
Damien429d7192013-10-04 19:53:11 +0100798 case O_LIST:
799 return "list";
Damienc226dca2013-10-16 16:12:52 +0100800 case O_TUPLE_IT:
801 return "tuple_iterator";
802 case O_LIST_IT:
803 return "list_iterator";
Damien429d7192013-10-04 19:53:11 +0100804 case O_SET:
805 return "set";
806 case O_MAP:
807 return "dict";
Damiena3977762013-10-09 23:10:10 +0100808 case O_OBJ:
809 {
810 py_map_elem_t *qn = py_qstr_map_lookup(o->u_obj.class->u_class.locals, qstr_from_str_static("__qualname__"), false);
811 assert(qn != NULL);
812 assert(IS_O(qn->value, O_STR));
813 return qstr_str(((py_obj_base_t*)qn->value)->u_str);
814 }
Damien429d7192013-10-04 19:53:11 +0100815 default:
816 assert(0);
817 return "UnknownType";
818 }
819 }
820}
821
822void py_obj_print(py_obj_t o_in) {
823 if (IS_SMALL_INT(o_in)) {
824 printf("%d", (int)FROM_SMALL_INT(o_in));
825 } else {
826 py_obj_base_t *o = o_in;
827 switch (o->kind) {
828 case O_CONST:
829 printf("%s", o->id);
830 break;
831 case O_STR:
832 // TODO need to escape chars etc
833 printf("'%s'", qstr_str(o->u_str));
834 break;
Damien3ef4abb2013-10-12 16:53:13 +0100835#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100836 case O_FLOAT:
Damien7410e442013-11-02 19:47:57 +0000837 printf("%.8g", o->u_float);
838 break;
839 case O_COMPLEX:
840 if (o->u_complex.real == 0) {
841 printf("%.8gj", o->u_complex.imag);
842 } else {
843 printf("(%.8g+%.8gj)", o->u_complex.real, o->u_complex.imag);
844 }
Damien429d7192013-10-04 19:53:11 +0100845 break;
846#endif
Damienbd254452013-10-16 20:39:12 +0100847 case O_EXCEPTION_0:
848 printf("%s", qstr_str(o->u_exc0.id));
849 break;
Damienf086ecf2013-10-22 16:05:11 +0100850 case O_EXCEPTION_N:
851 printf("%s: ", qstr_str(o->u_exc_n.id));
852 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 +0100853 break;
Damienbd254452013-10-16 20:39:12 +0100854 case O_GEN_INSTANCE:
855 printf("<generator object 'fun-name' at %p>", o);
856 break;
Damienc226dca2013-10-16 16:12:52 +0100857 case O_TUPLE:
858 printf("(");
859 for (int i = 0; i < o->u_tuple_list.len; i++) {
Damien429d7192013-10-04 19:53:11 +0100860 if (i > 0) {
861 printf(", ");
862 }
Damienc226dca2013-10-16 16:12:52 +0100863 py_obj_print(o->u_tuple_list.items[i]);
864 }
865 if (o->u_tuple_list.len == 1) {
866 printf(",");
867 }
868 printf(")");
869 break;
870 case O_LIST:
871 printf("[");
872 for (int i = 0; i < o->u_tuple_list.len; i++) {
873 if (i > 0) {
874 printf(", ");
875 }
876 py_obj_print(o->u_tuple_list.items[i]);
Damien429d7192013-10-04 19:53:11 +0100877 }
878 printf("]");
879 break;
880 case O_SET:
881 {
882 bool first = true;
883 printf("{");
884 for (int i = 0; i < o->u_set.alloc; i++) {
885 if (o->u_set.table[i] != NULL) {
886 if (!first) {
887 printf(", ");
888 }
889 first = false;
890 py_obj_print(o->u_set.table[i]);
891 }
892 }
893 printf("}");
894 break;
895 }
896 case O_MAP:
897 {
898 bool first = true;
899 printf("{");
900 for (int i = 0; i < o->u_map.alloc; i++) {
901 if (o->u_map.table[i].key != NULL) {
902 if (!first) {
903 printf(", ");
904 }
905 first = false;
906 py_obj_print(o->u_map.table[i].key);
907 printf(": ");
908 py_obj_print(o->u_map.table[i].value);
909 }
910 }
911 printf("}");
912 break;
913 }
914 default:
Damiena3977762013-10-09 23:10:10 +0100915 printf("<? %d>", o->kind);
Damien429d7192013-10-04 19:53:11 +0100916 assert(0);
917 }
918 }
919}
920
921int rt_is_true(py_obj_t arg) {
922 DEBUG_OP_printf("is true %p\n", arg);
923 if (IS_SMALL_INT(arg)) {
924 if (FROM_SMALL_INT(arg) == 0) {
925 return 0;
926 } else {
927 return 1;
928 }
929 } else if (arg == py_const_none) {
930 return 0;
931 } else if (arg == py_const_false) {
932 return 0;
933 } else if (arg == py_const_true) {
934 return 1;
935 } else {
936 assert(0);
937 return 0;
938 }
939}
940
Damien4ebb32f2013-11-02 14:33:10 +0000941machine_int_t py_get_int(py_obj_t arg) {
Damienc226dca2013-10-16 16:12:52 +0100942 if (arg == py_const_false) {
943 return 0;
944 } else if (arg == py_const_true) {
945 return 1;
946 } else if (IS_SMALL_INT(arg)) {
Damien429d7192013-10-04 19:53:11 +0100947 return FROM_SMALL_INT(arg);
948 } else {
949 assert(0);
950 return 0;
951 }
952}
953
Damien4ebb32f2013-11-02 14:33:10 +0000954machine_float_t py_obj_get_float(py_obj_t arg) {
955 if (arg == py_const_false) {
956 return 0;
957 } else if (arg == py_const_true) {
958 return 1;
959 } else if (IS_SMALL_INT(arg)) {
960 return FROM_SMALL_INT(arg);
961 } else if (IS_O(arg, O_FLOAT)) {
Damien7410e442013-11-02 19:47:57 +0000962 return ((py_obj_base_t*)arg)->u_float;
Damien4ebb32f2013-11-02 14:33:10 +0000963 } else {
964 assert(0);
965 return 0;
966 }
967}
968
Damien7410e442013-11-02 19:47:57 +0000969void py_obj_get_complex(py_obj_t arg, py_float_t *real, py_float_t *imag) {
970 if (arg == py_const_false) {
971 *real = 0;
972 *imag = 0;
973 } else if (arg == py_const_true) {
974 *real = 1;
975 *imag = 0;
976 } else if (IS_SMALL_INT(arg)) {
977 *real = FROM_SMALL_INT(arg);
978 *imag = 0;
979 } else if (IS_O(arg, O_FLOAT)) {
980 *real = ((py_obj_base_t*)arg)->u_float;
981 *imag = 0;
982 } else if (IS_O(arg, O_COMPLEX)) {
983 *real = ((py_obj_base_t*)arg)->u_complex.real;
984 *imag = ((py_obj_base_t*)arg)->u_complex.imag;
985 } else {
986 assert(0);
987 *real = 0;
988 *imag = 0;
989 }
990}
991
Damien9fc79332013-10-23 00:01:10 +0100992qstr py_get_qstr(py_obj_t arg) {
993 if (IS_O(arg, O_STR)) {
994 return ((py_obj_base_t*)arg)->u_str;
995 } else {
996 assert(0);
997 return 0;
998 }
999}
1000
Damien4ebb32f2013-11-02 14:33:10 +00001001py_obj_t *py_get_array_fixed_n(py_obj_t o_in, machine_int_t n) {
Damien28391682013-10-25 00:40:38 +01001002 if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) {
1003 py_obj_base_t *o = o_in;
1004 if (o->u_tuple_list.len != n) {
1005 nlr_jump(py_obj_new_exception_2(q_IndexError, "requested length %d but object has length %d", (void*)n, (void*)o->u_tuple_list.len));
1006 }
1007 return o->u_tuple_list.items;
1008 } else {
1009 nlr_jump(py_obj_new_exception_2(q_TypeError, "object '%s' is not a tuple or list", py_obj_get_type_str(o_in), NULL));
1010 }
1011}
1012
Damien7410e442013-11-02 19:47:57 +00001013#define PARSE_DEC_IN_INTG (1)
1014#define PARSE_DEC_IN_FRAC (2)
1015#define PARSE_DEC_IN_EXP (3)
1016
1017py_obj_t rt_load_const_dec(qstr qstr) {
1018#if MICROPY_ENABLE_FLOAT
1019 DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
1020 const char *s = qstr_str(qstr);
1021 int in = PARSE_DEC_IN_INTG;
1022 py_float_t dec_val = 0;
1023 bool exp_neg = false;
1024 int exp_val = 0;
1025 int exp_extra = 0;
1026 bool imag = false;
1027 for (; *s; s++) {
1028 int dig = *s;
1029 if ('0' <= dig && dig <= '9') {
1030 dig -= '0';
1031 if (in == PARSE_DEC_IN_EXP) {
1032 exp_val = 10 * exp_val + dig;
1033 } else {
1034 dec_val = 10 * dec_val + dig;
1035 if (in == PARSE_DEC_IN_FRAC) {
1036 exp_extra -= 1;
1037 }
1038 }
1039 } else if (in == PARSE_DEC_IN_INTG && dig == '.') {
1040 in = PARSE_DEC_IN_FRAC;
1041 } else if (in != PARSE_DEC_IN_EXP && (dig == 'E' || dig == 'e')) {
1042 in = PARSE_DEC_IN_EXP;
1043 if (s[1] == '+') {
1044 s++;
1045 } else if (s[1] == '-') {
1046 s++;
1047 exp_neg = true;
1048 }
1049 } else if (dig == 'J' || dig == 'j') {
1050 s++;
1051 imag = true;
1052 break;
1053 } else {
1054 // unknown character
1055 break;
1056 }
1057 }
1058 if (*s != 0) {
1059 nlr_jump(py_obj_new_exception_2(q_SyntaxError, "invalid syntax for number", NULL, NULL));
1060 }
1061 if (exp_neg) {
1062 exp_val = -exp_val;
1063 }
1064 exp_val += exp_extra;
1065 for (; exp_val > 0; exp_val--) {
1066 dec_val *= 10;
1067 }
1068 for (; exp_val < 0; exp_val++) {
1069 dec_val *= 0.1;
1070 }
1071 if (imag) {
1072 return py_obj_new_complex(0, dec_val);
1073 } else {
1074 return py_obj_new_float(dec_val);
1075 }
1076#else
1077 nlr_jump(py_obj_new_exception_2(q_SyntaxError, "decimal numbers not supported", NULL, NULL));
1078#endif
1079}
1080
Damien429d7192013-10-04 19:53:11 +01001081py_obj_t rt_load_const_str(qstr qstr) {
1082 DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
1083 return py_obj_new_str(qstr);
1084}
1085
1086py_obj_t rt_load_name(qstr qstr) {
1087 // logic: search locals, globals, builtins
Damiena3977762013-10-09 23:10:10 +01001088 DEBUG_OP_printf("load name %s\n", qstr_str(qstr));
Damieneb19efb2013-10-10 22:06:54 +01001089 py_map_elem_t *elem = py_qstr_map_lookup(map_locals, qstr, false);
Damiena3977762013-10-09 23:10:10 +01001090 if (elem == NULL) {
Damieneb19efb2013-10-10 22:06:54 +01001091 elem = py_qstr_map_lookup(map_globals, qstr, false);
Damiena3977762013-10-09 23:10:10 +01001092 if (elem == NULL) {
1093 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
1094 if (elem == NULL) {
Damience89a212013-10-15 22:25:17 +01001095 nlr_jump(py_obj_new_exception_2(q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL));
Damiena3977762013-10-09 23:10:10 +01001096 }
1097 }
1098 }
1099 return elem->value;
1100}
1101
1102py_obj_t rt_load_global(qstr qstr) {
1103 // logic: search globals, builtins
1104 DEBUG_OP_printf("load global %s\n", qstr_str(qstr));
Damieneb19efb2013-10-10 22:06:54 +01001105 py_map_elem_t *elem = py_qstr_map_lookup(map_globals, qstr, false);
Damien429d7192013-10-04 19:53:11 +01001106 if (elem == NULL) {
1107 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
1108 if (elem == NULL) {
Damience89a212013-10-15 22:25:17 +01001109 nlr_jump(py_obj_new_exception_2(q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL));
Damien429d7192013-10-04 19:53:11 +01001110 }
1111 }
1112 return elem->value;
1113}
1114
Damien8b3a7c22013-10-23 20:20:17 +01001115py_obj_t rt_load_build_class(void) {
Damien429d7192013-10-04 19:53:11 +01001116 DEBUG_OP_printf("load_build_class\n");
1117 py_map_elem_t *elem = py_qstr_map_lookup(&map_builtins, q___build_class__, false);
1118 if (elem == NULL) {
1119 printf("name doesn't exist: __build_class__\n");
1120 assert(0);
1121 }
1122 return elem->value;
1123}
1124
1125void rt_store_name(qstr qstr, py_obj_t obj) {
Damiena3977762013-10-09 23:10:10 +01001126 DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qstr), obj);
Damieneb19efb2013-10-10 22:06:54 +01001127 py_qstr_map_lookup(map_locals, qstr, true)->value = obj;
Damiena3977762013-10-09 23:10:10 +01001128}
1129
1130void rt_store_global(qstr qstr, py_obj_t obj) {
1131 DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qstr), obj);
Damieneb19efb2013-10-10 22:06:54 +01001132 py_qstr_map_lookup(map_globals, qstr, true)->value = obj;
Damien429d7192013-10-04 19:53:11 +01001133}
1134
1135py_obj_t rt_unary_op(int op, py_obj_t arg) {
Damien7410e442013-11-02 19:47:57 +00001136 DEBUG_OP_printf("unary %d %p\n", op, arg);
1137 if (IS_SMALL_INT(arg)) {
1138 py_small_int_t val = FROM_SMALL_INT(arg);
1139 switch (op) {
1140 case RT_UNARY_OP_NOT: if (val != 0) { return py_const_true;} else { return py_const_false; }
1141 case RT_UNARY_OP_POSITIVE: break;
1142 case RT_UNARY_OP_NEGATIVE: val = -val; break;
1143 case RT_UNARY_OP_INVERT: val = ~val; break;
1144 default: assert(0); val = 0;
1145 }
1146 if (fit_small_int(val)) {
1147 return TO_SMALL_INT(val);
1148 }
1149#if MICROPY_ENABLE_FLOAT
1150 } else if (IS_O(arg, O_FLOAT)) {
1151 py_float_t val = py_obj_get_float(arg);
1152 switch (op) {
1153 case RT_UNARY_OP_NOT: if (val != 0) { return py_const_true;} else { return py_const_false; }
1154 case RT_UNARY_OP_POSITIVE: break;
1155 case RT_UNARY_OP_NEGATIVE: val = -val; break;
1156 case RT_UNARY_OP_INVERT: nlr_jump(py_obj_new_exception_2(q_TypeError, "bad operand type for unary ~: 'float'", NULL, NULL));
1157 default: assert(0); val = 0;
1158 }
1159 return py_obj_new_float(val);
1160#endif
1161 }
Damien429d7192013-10-04 19:53:11 +01001162 assert(0);
1163 return py_const_none;
1164}
1165
Damienc226dca2013-10-16 16:12:52 +01001166uint get_index(py_obj_base_t *base, py_obj_t index) {
1167 // assumes base is O_TUPLE or O_LIST
1168 // TODO False and True are considered 0 and 1 for indexing purposes
1169 int len = base->u_tuple_list.len;
1170 if (IS_SMALL_INT(index)) {
1171 int i = FROM_SMALL_INT(index);
1172 if (i < 0) {
1173 i += len;
1174 }
1175 if (i < 0 || i >= len) {
1176 nlr_jump(py_obj_new_exception_2(q_IndexError, "%s index out of range", py_obj_get_type_str(base), NULL));
1177 }
1178 return i;
1179 } else {
1180 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)));
1181 }
1182}
1183
Damien429d7192013-10-04 19:53:11 +01001184py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs) {
1185 DEBUG_OP_printf("binary %d %p %p\n", op, lhs, rhs);
1186 if (op == RT_BINARY_OP_SUBSCR) {
Damienc226dca2013-10-16 16:12:52 +01001187 if ((IS_O(lhs, O_TUPLE) || IS_O(lhs, O_LIST))) {
Damien5ac1b2e2013-10-18 19:58:12 +01001188 // tuple/list load
Damienc226dca2013-10-16 16:12:52 +01001189 uint index = get_index(lhs, rhs);
1190 return ((py_obj_base_t*)lhs)->u_tuple_list.items[index];
Damien5ac1b2e2013-10-18 19:58:12 +01001191 } else if (IS_O(lhs, O_MAP)) {
1192 // map load
1193 py_map_elem_t *elem = py_map_lookup(lhs, rhs, false);
1194 if (elem == NULL) {
1195 nlr_jump(py_obj_new_exception_2(q_KeyError, "<value>", NULL, NULL));
1196 } else {
1197 return elem->value;
1198 }
Damien429d7192013-10-04 19:53:11 +01001199 } else {
1200 assert(0);
1201 }
1202 } else if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
Damien4ebb32f2013-11-02 14:33:10 +00001203 py_small_int_t lhs_val = FROM_SMALL_INT(lhs);
1204 py_small_int_t rhs_val = FROM_SMALL_INT(rhs);
Damien429d7192013-10-04 19:53:11 +01001205 switch (op) {
Damien7b2d3f32013-10-22 16:53:02 +01001206 case RT_BINARY_OP_OR:
Damien7410e442013-11-02 19:47:57 +00001207 case RT_BINARY_OP_INPLACE_OR: lhs_val |= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001208 case RT_BINARY_OP_XOR:
Damien7410e442013-11-02 19:47:57 +00001209 case RT_BINARY_OP_INPLACE_XOR: lhs_val ^= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001210 case RT_BINARY_OP_AND:
Damien7410e442013-11-02 19:47:57 +00001211 case RT_BINARY_OP_INPLACE_AND: lhs_val &= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001212 case RT_BINARY_OP_LSHIFT:
Damien7410e442013-11-02 19:47:57 +00001213 case RT_BINARY_OP_INPLACE_LSHIFT: lhs_val <<= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001214 case RT_BINARY_OP_RSHIFT:
Damien7410e442013-11-02 19:47:57 +00001215 case RT_BINARY_OP_INPLACE_RSHIFT: lhs_val >>= rhs_val; break;
Damien429d7192013-10-04 19:53:11 +01001216 case RT_BINARY_OP_ADD:
Damien7410e442013-11-02 19:47:57 +00001217 case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
Damienbd254452013-10-16 20:39:12 +01001218 case RT_BINARY_OP_SUBTRACT:
Damien7410e442013-11-02 19:47:57 +00001219 case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001220 case RT_BINARY_OP_MULTIPLY:
Damien7410e442013-11-02 19:47:57 +00001221 case RT_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001222 case RT_BINARY_OP_FLOOR_DIVIDE:
Damien7410e442013-11-02 19:47:57 +00001223 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: lhs_val /= rhs_val; break;
Damien3ef4abb2013-10-12 16:53:13 +01001224#if MICROPY_ENABLE_FLOAT
Damien7b2d3f32013-10-22 16:53:02 +01001225 case RT_BINARY_OP_TRUE_DIVIDE:
Damien7410e442013-11-02 19:47:57 +00001226 case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: return py_obj_new_float((py_float_t)lhs_val / (py_float_t)rhs_val);
Damien429d7192013-10-04 19:53:11 +01001227#endif
Damien4ebb32f2013-11-02 14:33:10 +00001228 case RT_BINARY_OP_POWER:
1229 case RT_BINARY_OP_INPLACE_POWER:
1230 // TODO
1231 if (rhs_val == 2) {
Damien7410e442013-11-02 19:47:57 +00001232 lhs_val = lhs_val * lhs_val;
Damien4ebb32f2013-11-02 14:33:10 +00001233 break;
1234 }
Damien7410e442013-11-02 19:47:57 +00001235 default: printf("%d\n", op); assert(0);
Damien429d7192013-10-04 19:53:11 +01001236 }
Damien7410e442013-11-02 19:47:57 +00001237 if (fit_small_int(lhs_val)) {
1238 return TO_SMALL_INT(lhs_val);
Damien429d7192013-10-04 19:53:11 +01001239 }
Damien4ebb32f2013-11-02 14:33:10 +00001240#if MICROPY_ENABLE_FLOAT
Damien7410e442013-11-02 19:47:57 +00001241 } else if (IS_O(lhs, O_COMPLEX) || IS_O(rhs, O_COMPLEX)) {
1242 py_float_t lhs_real, lhs_imag, rhs_real, rhs_imag;
1243 py_obj_get_complex(lhs, &lhs_real, &lhs_imag);
1244 py_obj_get_complex(rhs, &rhs_real, &rhs_imag);
Damien4ebb32f2013-11-02 14:33:10 +00001245 switch (op) {
1246 case RT_BINARY_OP_ADD:
Damien7410e442013-11-02 19:47:57 +00001247 case RT_BINARY_OP_INPLACE_ADD:
1248 lhs_real += rhs_real;
1249 lhs_imag += rhs_imag;
1250 break;
Damien4ebb32f2013-11-02 14:33:10 +00001251 case RT_BINARY_OP_SUBTRACT:
Damien7410e442013-11-02 19:47:57 +00001252 case RT_BINARY_OP_INPLACE_SUBTRACT:
1253 lhs_real -= rhs_real;
1254 lhs_imag -= rhs_imag;
1255 break;
Damien4ebb32f2013-11-02 14:33:10 +00001256 case RT_BINARY_OP_MULTIPLY:
Damien7410e442013-11-02 19:47:57 +00001257 case RT_BINARY_OP_INPLACE_MULTIPLY:
1258 {
1259 py_float_t real = lhs_real * rhs_real - lhs_imag * rhs_imag;
1260 lhs_imag = lhs_real * rhs_imag + lhs_imag * rhs_real;
1261 lhs_real = real;
1262 break;
1263 }
1264 /* TODO floor(?) the value
1265 case RT_BINARY_OP_FLOOR_DIVIDE:
1266 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break;
1267 */
1268 /* TODO
1269 case RT_BINARY_OP_TRUE_DIVIDE:
1270 case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: val = lhs_val / rhs_val; break;
1271 */
1272 default: printf("%d\n", op); assert(0);
1273 }
1274 return py_obj_new_complex(lhs_real, lhs_imag);
1275 } else if (IS_O(lhs, O_FLOAT) || IS_O(rhs, O_FLOAT)) {
1276 py_float_t lhs_val = py_obj_get_float(lhs);
1277 py_float_t rhs_val = py_obj_get_float(rhs);
1278 switch (op) {
1279 case RT_BINARY_OP_ADD:
1280 case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
1281 case RT_BINARY_OP_SUBTRACT:
1282 case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
1283 case RT_BINARY_OP_MULTIPLY:
1284 case RT_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;
Damien4ebb32f2013-11-02 14:33:10 +00001285 /* TODO floor(?) the value
1286 case RT_BINARY_OP_FLOOR_DIVIDE:
1287 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break;
1288 */
1289 case RT_BINARY_OP_TRUE_DIVIDE:
Damien7410e442013-11-02 19:47:57 +00001290 case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: lhs_val /= rhs_val; break;
1291 default: printf("%d\n", op); assert(0);
Damien4ebb32f2013-11-02 14:33:10 +00001292 }
Damien7410e442013-11-02 19:47:57 +00001293 return py_obj_new_float(lhs_val);
Damien4ebb32f2013-11-02 14:33:10 +00001294#endif
Damien429d7192013-10-04 19:53:11 +01001295 } else if (IS_O(lhs, O_STR) && IS_O(rhs, O_STR)) {
1296 const char *lhs_str = qstr_str(((py_obj_base_t*)lhs)->u_str);
1297 const char *rhs_str = qstr_str(((py_obj_base_t*)rhs)->u_str);
1298 char *val;
1299 switch (op) {
1300 case RT_BINARY_OP_ADD:
1301 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;
1302 default: printf("%d\n", op); assert(0); val = NULL;
1303 }
1304 return py_obj_new_str(qstr_from_str_take(val));
1305 }
1306 assert(0);
1307 return py_const_none;
1308}
1309
1310py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs) {
1311 DEBUG_OP_printf("compare %d %p %p\n", op, lhs, rhs);
Damien7b2d3f32013-10-22 16:53:02 +01001312
1313 // deal with == and !=
1314 if (op == RT_COMPARE_OP_EQUAL || op == RT_COMPARE_OP_NOT_EQUAL) {
1315 if (py_obj_equal(lhs, rhs)) {
1316 if (op == RT_COMPARE_OP_EQUAL) {
1317 return py_const_true;
1318 } else {
1319 return py_const_false;
1320 }
1321 } else {
1322 if (op == RT_COMPARE_OP_EQUAL) {
1323 return py_const_false;
1324 } else {
1325 return py_const_true;
1326 }
1327 }
1328 }
1329
1330 // deal with small ints
Damien429d7192013-10-04 19:53:11 +01001331 if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
Damien4ebb32f2013-11-02 14:33:10 +00001332 py_small_int_t lhs_val = FROM_SMALL_INT(lhs);
1333 py_small_int_t rhs_val = FROM_SMALL_INT(rhs);
Damien429d7192013-10-04 19:53:11 +01001334 int cmp;
1335 switch (op) {
Damien4ebb32f2013-11-02 14:33:10 +00001336 case RT_COMPARE_OP_LESS: cmp = lhs_val < rhs_val; break;
1337 case RT_COMPARE_OP_MORE: cmp = lhs_val > rhs_val; break;
1338 case RT_COMPARE_OP_LESS_EQUAL: cmp = lhs_val <= rhs_val; break;
1339 case RT_COMPARE_OP_MORE_EQUAL: cmp = lhs_val >= rhs_val; break;
Damien429d7192013-10-04 19:53:11 +01001340 default: assert(0); cmp = 0;
1341 }
1342 if (cmp) {
1343 return py_const_true;
1344 } else {
1345 return py_const_false;
1346 }
1347 }
Damien7b2d3f32013-10-22 16:53:02 +01001348
Damien4ebb32f2013-11-02 14:33:10 +00001349#if MICROPY_ENABLE_FLOAT
1350 // deal with floats
1351 if (IS_O(lhs, O_FLOAT) || IS_O(rhs, O_FLOAT)) {
Damien7410e442013-11-02 19:47:57 +00001352 py_float_t lhs_val = py_obj_get_float(lhs);
1353 py_float_t rhs_val = py_obj_get_float(rhs);
Damien4ebb32f2013-11-02 14:33:10 +00001354 int cmp;
1355 switch (op) {
1356 case RT_COMPARE_OP_LESS: cmp = lhs_val < rhs_val; break;
1357 case RT_COMPARE_OP_MORE: cmp = lhs_val > rhs_val; break;
1358 case RT_COMPARE_OP_LESS_EQUAL: cmp = lhs_val <= rhs_val; break;
1359 case RT_COMPARE_OP_MORE_EQUAL: cmp = lhs_val >= rhs_val; break;
1360 default: assert(0); cmp = 0;
1361 }
1362 if (cmp) {
1363 return py_const_true;
1364 } else {
1365 return py_const_false;
1366 }
1367 }
1368#endif
1369
Damien7b2d3f32013-10-22 16:53:02 +01001370 // not implemented
Damien429d7192013-10-04 19:53:11 +01001371 assert(0);
1372 return py_const_none;
1373}
1374
1375py_obj_t rt_make_function_from_id(int unique_code_id) {
Damienb05d7072013-10-05 13:37:10 +01001376 DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id);
1377 if (unique_code_id < 1 || unique_code_id >= next_unique_code_id) {
Damien429d7192013-10-04 19:53:11 +01001378 // illegal code id
1379 return py_const_none;
1380 }
1381 py_code_t *c = &unique_codes[unique_code_id];
1382 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1383 switch (c->kind) {
Damien826005c2013-10-05 23:17:28 +01001384 case PY_CODE_BYTE:
1385 o->kind = O_FUN_BC;
1386 o->u_fun_bc.n_args = c->n_args;
1387 o->u_fun_bc.code = c->u_byte.code;
1388 o->u_fun_bc.len = c->u_byte.len;
1389 break;
Damien429d7192013-10-04 19:53:11 +01001390 case PY_CODE_NATIVE:
1391 switch (c->n_args) {
1392 case 0: o->kind = O_FUN_0; break;
1393 case 1: o->kind = O_FUN_1; break;
1394 case 2: o->kind = O_FUN_2; break;
1395 default: assert(0);
1396 }
1397 o->u_fun.fun = c->u_native.fun;
1398 break;
Damien826005c2013-10-05 23:17:28 +01001399 case PY_CODE_INLINE_ASM:
1400 o->kind = O_FUN_ASM;
1401 o->u_fun_asm.n_args = c->n_args;
1402 o->u_fun_asm.fun = c->u_inline_asm.fun;
Damien429d7192013-10-04 19:53:11 +01001403 break;
1404 default:
1405 assert(0);
1406 }
Damienbd254452013-10-16 20:39:12 +01001407
1408 // check for generator functions and if so wrap in generator object
1409 if (c->is_generator) {
1410 py_obj_base_t *o2 = m_new(py_obj_base_t, 1);
1411 o2->kind = O_GEN_WRAP;
1412 // we have at least 3 locals so the bc can write back fast[0,1,2] safely; should improve how this is done
1413 o2->u_gen_wrap.n_state = (c->n_locals < 3 ? 3 : c->n_locals) + c->n_stack;
1414 o2->u_gen_wrap.fun = o;
1415 o = o2;
1416 }
1417
Damien429d7192013-10-04 19:53:11 +01001418 return o;
1419}
1420
1421py_obj_t rt_make_function_0(py_fun_0_t fun) {
1422 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1423 o->kind = O_FUN_0;
1424 o->u_fun.fun = fun;
1425 return o;
1426}
1427
1428py_obj_t rt_make_function_1(py_fun_1_t fun) {
1429 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1430 o->kind = O_FUN_1;
1431 o->u_fun.fun = fun;
1432 return o;
1433}
1434
1435py_obj_t rt_make_function_2(py_fun_2_t fun) {
1436 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1437 o->kind = O_FUN_2;
1438 o->u_fun.fun = fun;
1439 return o;
1440}
1441
1442py_obj_t rt_make_function(int n_args, py_fun_t code) {
1443 // assumes code is a pointer to a py_fun_t (i think this is safe...)
1444 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1445 o->kind = O_FUN_N;
Damien429d7192013-10-04 19:53:11 +01001446 o->u_fun.n_args = n_args;
Damien826005c2013-10-05 23:17:28 +01001447 o->u_fun.fun = code;
Damien429d7192013-10-04 19:53:11 +01001448 return o;
1449}
1450
Damieneb19efb2013-10-10 22:06:54 +01001451py_obj_t rt_call_function_0(py_obj_t fun) {
1452 return rt_call_function_n(fun, 0, NULL);
1453}
1454
1455py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) {
1456 return rt_call_function_n(fun, 1, &arg);
1457}
1458
1459py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) {
1460 py_obj_t args[2];
1461 args[1] = arg1;
1462 args[0] = arg2;
1463 return rt_call_function_n(fun, 2, args);
1464}
1465
1466typedef machine_uint_t (*inline_asm_fun_0_t)();
1467typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t);
1468typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t);
1469typedef machine_uint_t (*inline_asm_fun_3_t)(machine_uint_t, machine_uint_t, machine_uint_t);
1470
Damiene4af64f2013-10-06 12:04:13 +01001471// convert a Python object to a sensible value for inline asm
1472machine_uint_t rt_convert_obj_for_inline_asm(py_obj_t obj) {
1473 // TODO for byte_array, pass pointer to the array
1474 if (IS_SMALL_INT(obj)) {
1475 return FROM_SMALL_INT(obj);
1476 } else if (obj == py_const_none) {
1477 return 0;
1478 } else if (obj == py_const_false) {
1479 return 0;
1480 } else if (obj == py_const_true) {
1481 return 1;
1482 } else {
1483 py_obj_base_t *o = obj;
1484 switch (o->kind) {
1485 case O_STR:
1486 // pointer to the string (it's probably constant though!)
1487 return (machine_uint_t)qstr_str(o->u_str);
1488
Damien3ef4abb2013-10-12 16:53:13 +01001489#if MICROPY_ENABLE_FLOAT
Damiene4af64f2013-10-06 12:04:13 +01001490 case O_FLOAT:
1491 // convert float to int (could also pass in float registers)
Damien7410e442013-11-02 19:47:57 +00001492 return (machine_int_t)o->u_float;
Damienc025ebb2013-10-12 14:30:21 +01001493#endif
Damiene4af64f2013-10-06 12:04:13 +01001494
Damienc226dca2013-10-16 16:12:52 +01001495 case O_TUPLE:
Damiene4af64f2013-10-06 12:04:13 +01001496 case O_LIST:
Damienc226dca2013-10-16 16:12:52 +01001497 // pointer to start of tuple/list (could pass length, but then could use len(x) for that)
1498 return (machine_uint_t)o->u_tuple_list.items;
Damiene4af64f2013-10-06 12:04:13 +01001499
1500 default:
1501 // just pass along a pointer to the object
1502 return (machine_uint_t)obj;
1503 }
1504 }
1505}
1506
1507// convert a return value from inline asm to a sensible Python object
1508py_obj_t rt_convert_val_from_inline_asm(machine_uint_t val) {
1509 return TO_SMALL_INT(val);
1510}
1511
Damieneb19efb2013-10-10 22:06:54 +01001512// args are in reverse order in the array
1513py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args) {
1514 int n_args_fun = 0;
Damien429d7192013-10-04 19:53:11 +01001515 if (IS_O(fun, O_FUN_0)) {
1516 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001517 if (n_args != 0) {
1518 n_args_fun = 0;
1519 goto bad_n_args;
1520 }
1521 DEBUG_OP_printf("calling native %p()\n", o->u_fun.fun);
Damien429d7192013-10-04 19:53:11 +01001522 return ((py_fun_0_t)o->u_fun.fun)();
Damieneb19efb2013-10-10 22:06:54 +01001523
1524 } else if (IS_O(fun, O_FUN_1)) {
1525 py_obj_base_t *o = fun;
1526 if (n_args != 1) {
1527 n_args_fun = 1;
1528 goto bad_n_args;
1529 }
1530 DEBUG_OP_printf("calling native %p(%p)\n", o->u_fun.fun, args[0]);
1531 return ((py_fun_1_t)o->u_fun.fun)(args[0]);
1532
1533 } else if (IS_O(fun, O_FUN_2)) {
1534 py_obj_base_t *o = fun;
1535 if (n_args != 2) {
1536 n_args_fun = 2;
1537 goto bad_n_args;
1538 }
1539 DEBUG_OP_printf("calling native %p(%p, %p)\n", o->u_fun.fun, args[1], args[0]);
1540 return ((py_fun_2_t)o->u_fun.fun)(args[1], args[0]);
1541
1542 // TODO O_FUN_N
1543
Damien429d7192013-10-04 19:53:11 +01001544 } else if (IS_O(fun, O_FUN_BC)) {
1545 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001546 if (n_args != o->u_fun_bc.n_args) {
1547 n_args_fun = o->u_fun_bc.n_args;
1548 goto bad_n_args;
1549 }
1550 DEBUG_OP_printf("calling byte code %p(n_args=%d)\n", o->u_fun_bc.code, n_args);
Damienbd254452013-10-16 20:39:12 +01001551 return py_execute_byte_code(o->u_fun_bc.code, args, n_args);
Damieneb19efb2013-10-10 22:06:54 +01001552
Damiene4af64f2013-10-06 12:04:13 +01001553 } else if (IS_O(fun, O_FUN_ASM)) {
1554 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001555 if (n_args != o->u_fun_asm.n_args) {
1556 n_args_fun = o->u_fun_asm.n_args;
1557 goto bad_n_args;
1558 }
1559 DEBUG_OP_printf("calling inline asm %p(n_args=%d)\n", o->u_fun_asm.fun, n_args);
1560 machine_uint_t ret;
1561 if (n_args == 0) {
1562 ret = ((inline_asm_fun_0_t)o->u_fun_asm.fun)();
1563 } else if (n_args == 1) {
1564 ret = ((inline_asm_fun_1_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[0]));
1565 } else if (n_args == 2) {
1566 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]));
1567 } else if (n_args == 3) {
1568 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]));
1569 } else {
1570 assert(0);
1571 ret = 0;
1572 }
1573 return rt_convert_val_from_inline_asm(ret);
1574
Damienbd254452013-10-16 20:39:12 +01001575 } else if (IS_O(fun, O_GEN_WRAP)) {
1576 py_obj_base_t *o = fun;
1577 py_obj_base_t *o_fun = o->u_gen_wrap.fun;
1578 assert(o_fun->kind == O_FUN_BC); // TODO
1579 if (n_args != o_fun->u_fun_bc.n_args) {
1580 n_args_fun = o_fun->u_fun_bc.n_args;
1581 goto bad_n_args;
1582 }
1583 py_obj_t *state = m_new(py_obj_t, 1 + o->u_gen_wrap.n_state);
1584 // put function object at first slot in state (to keep u_gen_instance small)
1585 state[0] = o_fun;
1586 // init args
1587 for (int i = 0; i < n_args; i++) {
1588 state[1 + i] = args[n_args - 1 - i];
1589 }
1590 py_obj_base_t *o2 = m_new(py_obj_base_t, 1);
1591 o2->kind = O_GEN_INSTANCE;
1592 o2->u_gen_instance.state = state;
1593 o2->u_gen_instance.ip = o_fun->u_fun_bc.code;
1594 o2->u_gen_instance.sp = state + o->u_gen_wrap.n_state;
1595 return o2;
1596
Damiena3977762013-10-09 23:10:10 +01001597 } else if (IS_O(fun, O_BOUND_METH)) {
1598 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001599 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);
1600 if (n_args == 0) {
1601 return rt_call_function_n(o->u_bound_meth.meth, 1, &o->u_bound_meth.self);
1602 } else if (n_args == 1) {
1603 py_obj_t args2[2];
1604 args2[1] = o->u_bound_meth.self;
1605 args2[0] = args[0];
1606 return rt_call_function_n(o->u_bound_meth.meth, 2, args2);
1607 } else {
1608 // TODO not implemented
1609 assert(0);
1610 return py_const_none;
1611 //return rt_call_function_2(o->u_bound_meth.meth, n_args + 1, o->u_bound_meth.self + args);
1612 }
1613
Damiena3977762013-10-09 23:10:10 +01001614 } else if (IS_O(fun, O_CLASS)) {
1615 // instantiate an instance of a class
Damieneb19efb2013-10-10 22:06:54 +01001616 if (n_args != 0) {
1617 n_args_fun = 0;
1618 goto bad_n_args;
1619 }
Damiena3977762013-10-09 23:10:10 +01001620 DEBUG_OP_printf("instantiate object of class %p with no args\n", fun);
1621 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1622 o->kind = O_OBJ;
1623 o->u_obj.class = fun;
1624 o->u_obj.members = py_map_new(MAP_QSTR, 0);
1625 return o;
Damieneb19efb2013-10-10 22:06:54 +01001626
Damien429d7192013-10-04 19:53:11 +01001627 } else {
Damieneb19efb2013-10-10 22:06:54 +01001628 printf("fun %p %d\n", fun, ((py_obj_base_t*)fun)->kind);
Damien429d7192013-10-04 19:53:11 +01001629 assert(0);
1630 return py_const_none;
1631 }
Damien429d7192013-10-04 19:53:11 +01001632
Damieneb19efb2013-10-10 22:06:54 +01001633bad_n_args:
Damienbd254452013-10-16 20:39:12 +01001634 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 +01001635}
1636
Damiena3977762013-10-09 23:10:10 +01001637// args contains: arg(n_args-1) arg(n_args-2) ... arg(0) self/NULL fun
1638// if n_args==0 then there are only self/NULL and fun
1639py_obj_t rt_call_method_n(int n_args, const py_obj_t *args) {
Damien7f5dacf2013-10-10 11:24:39 +01001640 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 +01001641 return rt_call_function_n(args[n_args + 1], n_args + ((args[n_args] == NULL) ? 0 : 1), args);
1642}
1643
Damien429d7192013-10-04 19:53:11 +01001644// items are in reverse order
Damienc226dca2013-10-16 16:12:52 +01001645py_obj_t rt_build_tuple(int n_args, py_obj_t *items) {
1646 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1647 o->kind = O_TUPLE;
1648 o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args;
1649 o->u_tuple_list.len = n_args;
1650 o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc);
1651 for (int i = 0; i < n_args; i++) {
1652 o->u_tuple_list.items[i] = items[n_args - i - 1];
1653 }
1654 return o;
1655}
1656
1657// items are in reverse order
Damien429d7192013-10-04 19:53:11 +01001658py_obj_t rt_build_list(int n_args, py_obj_t *items) {
1659 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1660 o->kind = O_LIST;
Damienc226dca2013-10-16 16:12:52 +01001661 o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args;
1662 o->u_tuple_list.len = n_args;
1663 o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc);
Damien429d7192013-10-04 19:53:11 +01001664 for (int i = 0; i < n_args; i++) {
Damienc226dca2013-10-16 16:12:52 +01001665 o->u_tuple_list.items[i] = items[n_args - i - 1];
Damien429d7192013-10-04 19:53:11 +01001666 }
1667 return o;
1668}
1669
1670py_obj_t py_set_lookup(py_obj_t o_in, py_obj_t index, bool add_if_not_found) {
1671 assert(IS_O(o_in, O_SET));
1672 py_obj_base_t *o = o_in;
1673 int hash = py_obj_hash(index);
1674 int pos = hash % o->u_set.alloc;
1675 for (;;) {
1676 py_obj_t elem = o->u_set.table[pos];
1677 if (elem == NULL) {
1678 // not in table
1679 if (add_if_not_found) {
1680 if (o->u_set.used + 1 >= o->u_set.alloc) {
1681 // not enough room in table, rehash it
1682 int old_alloc = o->u_set.alloc;
1683 py_obj_t *old_table = o->u_set.table;
1684 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(o->u_set.alloc + 1);
1685 o->u_set.used = 0;
1686 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
1687 for (int i = 0; i < old_alloc; i++) {
1688 if (old_table[i] != NULL) {
1689 py_set_lookup(o, old_table[i], true);
1690 }
1691 }
1692 m_free(old_table);
1693 // restart the search for the new element
1694 pos = hash % o->u_set.alloc;
1695 } else {
1696 o->u_set.used += 1;
1697 o->u_set.table[pos] = index;
1698 return index;
1699 }
1700 } else {
1701 return NULL;
1702 }
1703 } else if (py_obj_equal(elem, index)) {
1704 // found it
1705 return elem;
1706 } else {
1707 // not yet found, keep searching in this table
1708 pos = (pos + 1) % o->u_set.alloc;
1709 }
1710 }
1711}
1712
1713py_obj_t rt_build_set(int n_args, py_obj_t *items) {
1714 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1715 o->kind = O_SET;
1716 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(n_args + 1);
1717 o->u_set.used = 0;
1718 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
1719 for (int i = 0; i < o->u_set.alloc; i++) {
1720 o->u_set.table[i] = NULL;
1721 }
1722 for (int i = 0; i < n_args; i++) {
1723 py_set_lookup(o, items[i], true);
1724 }
1725 return o;
1726}
1727
Damienc12aa462013-10-16 20:57:49 +01001728py_obj_t rt_store_set(py_obj_t set, py_obj_t item) {
1729 py_set_lookup(set, item, true);
1730 return set;
1731}
1732
Damien429d7192013-10-04 19:53:11 +01001733py_obj_t rt_build_map(int n_args) {
1734 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1735 o->kind = O_MAP;
1736 py_map_init(&o->u_map, MAP_PY_OBJ, n_args);
1737 return o;
1738}
1739
1740py_obj_t rt_store_map(py_obj_t map, py_obj_t key, py_obj_t value) {
1741 assert(IS_O(map, O_MAP)); // should always be
1742 py_map_lookup(map, key, true)->value = value;
1743 return map;
1744}
1745
Damiena3977762013-10-09 23:10:10 +01001746py_obj_t build_bound_method(py_obj_t self, py_obj_t meth) {
1747 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1748 o->kind = O_BOUND_METH;
1749 o->u_bound_meth.meth = meth;
1750 o->u_bound_meth.self = self;
1751 return o;
1752}
1753
1754py_obj_t rt_load_attr(py_obj_t base, qstr attr) {
1755 DEBUG_OP_printf("load attr %s\n", qstr_str(attr));
1756 if (IS_O(base, O_LIST) && attr == q_append) {
1757 return build_bound_method(base, fun_list_append);
1758 } else if (IS_O(base, O_CLASS)) {
1759 py_obj_base_t *o = base;
1760 py_map_elem_t *elem = py_qstr_map_lookup(o->u_class.locals, attr, false);
1761 if (elem == NULL) {
1762 goto no_attr;
1763 }
1764 return elem->value;
1765 } else if (IS_O(base, O_OBJ)) {
1766 // logic: look in obj members then class locals (TODO check this against CPython)
1767 py_obj_base_t *o = base;
1768 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false);
1769 if (elem != NULL) {
1770 // object member, always treated as a value
1771 return elem->value;
1772 }
1773 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1774 if (elem != NULL) {
1775 if (py_obj_is_callable(elem->value)) {
1776 // class member is callable so build a bound method
1777 return build_bound_method(base, elem->value);
1778 } else {
1779 // class member is a value, so just return that value
1780 return elem->value;
1781 }
1782 }
1783 goto no_attr;
1784 }
1785
1786no_attr:
Damience89a212013-10-15 22:25:17 +01001787 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 +01001788}
1789
1790void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest) {
1791 DEBUG_OP_printf("load method %s\n", qstr_str(attr));
Damien4ebb32f2013-11-02 14:33:10 +00001792 if (IS_O(base, O_STR) && attr == q_join) {
1793 dest[1] = fun_str_join;
1794 dest[0] = base;
1795 return;
1796 } else if (IS_O(base, O_GEN_INSTANCE) && attr == q___next__) {
Damienbd254452013-10-16 20:39:12 +01001797 dest[1] = fun_gen_instance_next;
1798 dest[0] = base;
1799 return;
1800 } else if (IS_O(base, O_LIST) && attr == q_append) {
Damiena3977762013-10-09 23:10:10 +01001801 dest[1] = fun_list_append;
1802 dest[0] = base;
1803 return;
1804 } else if (IS_O(base, O_OBJ)) {
1805 // logic: look in obj members then class locals (TODO check this against CPython)
1806 py_obj_base_t *o = base;
1807 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false);
1808 if (elem != NULL) {
1809 // object member, always treated as a value
1810 dest[1] = elem->value;
1811 dest[0] = NULL;
1812 return;
1813 }
1814 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1815 if (elem != NULL) {
1816 if (py_obj_is_callable(elem->value)) {
1817 // class member is callable so build a bound method
1818 dest[1] = elem->value;
1819 dest[0] = base;
1820 return;
1821 } else {
1822 // class member is a value, so just return that value
1823 dest[1] = elem->value;
1824 dest[0] = NULL;
1825 return;
1826 }
1827 }
1828 goto no_attr;
1829 }
1830
1831no_attr:
1832 dest[1] = rt_load_attr(base, attr);
1833 dest[0] = NULL;
1834}
1835
Damien5ac1b2e2013-10-18 19:58:12 +01001836void rt_store_attr(py_obj_t base, qstr attr, py_obj_t value) {
1837 DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value);
Damienec63cce2013-10-22 22:58:17 +01001838 if (IS_O(base, O_CLASS)) {
1839 // TODO CPython allows STORE_ATTR to a class, but is this the correct implementation?
1840 py_obj_base_t *o = base;
1841 py_qstr_map_lookup(o->u_class.locals, attr, true)->value = value;
1842 } else if (IS_O(base, O_OBJ)) {
Damiena3977762013-10-09 23:10:10 +01001843 // logic: look in class locals (no add) then obj members (add) (TODO check this against CPython)
1844 py_obj_base_t *o = base;
1845 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1846 if (elem != NULL) {
Damien5ac1b2e2013-10-18 19:58:12 +01001847 elem->value = value;
Damiena3977762013-10-09 23:10:10 +01001848 } else {
Damienec63cce2013-10-22 22:58:17 +01001849 py_qstr_map_lookup(o->u_obj.members, attr, true)->value = value;
Damiena3977762013-10-09 23:10:10 +01001850 }
1851 } else {
1852 printf("?AttributeError: '%s' object has no attribute '%s'\n", py_obj_get_type_str(base), qstr_str(attr));
1853 assert(0);
1854 }
1855}
1856
Damien429d7192013-10-04 19:53:11 +01001857void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t value) {
Damien5ac1b2e2013-10-18 19:58:12 +01001858 DEBUG_OP_printf("store subscr %p[%p] <- %p\n", base, index, value);
Damienc226dca2013-10-16 16:12:52 +01001859 if (IS_O(base, O_LIST)) {
Damien429d7192013-10-04 19:53:11 +01001860 // list store
Damienc226dca2013-10-16 16:12:52 +01001861 uint i = get_index(base, index);
1862 ((py_obj_base_t*)base)->u_tuple_list.items[i] = value;
Damien429d7192013-10-04 19:53:11 +01001863 } else if (IS_O(base, O_MAP)) {
1864 // map store
1865 py_map_lookup(base, index, true)->value = value;
1866 } else {
1867 assert(0);
1868 }
1869}
1870
Damience89a212013-10-15 22:25:17 +01001871py_obj_t rt_getiter(py_obj_t o_in) {
Damienbd254452013-10-16 20:39:12 +01001872 if (IS_O(o_in, O_GEN_INSTANCE)) {
1873 return o_in;
1874 } else if (IS_O(o_in, O_RANGE)) {
Damience89a212013-10-15 22:25:17 +01001875 py_obj_base_t *o = o_in;
1876 return py_obj_new_range_iterator(o->u_range.start, o->u_range.stop, o->u_range.step);
Damienc226dca2013-10-16 16:12:52 +01001877 } else if (IS_O(o_in, O_TUPLE)) {
1878 return py_obj_new_tuple_iterator(o_in, 0);
1879 } else if (IS_O(o_in, O_LIST)) {
1880 return py_obj_new_list_iterator(o_in, 0);
Damience89a212013-10-15 22:25:17 +01001881 } else {
1882 nlr_jump(py_obj_new_exception_2(q_TypeError, "'%s' object is not iterable", py_obj_get_type_str(o_in), NULL));
1883 }
1884}
1885
1886py_obj_t rt_iternext(py_obj_t o_in) {
Damienbd254452013-10-16 20:39:12 +01001887 if (IS_O(o_in, O_GEN_INSTANCE)) {
1888 py_obj_base_t *self = o_in;
1889 py_obj_base_t *fun = self->u_gen_instance.state[0];
1890 assert(fun->kind == O_FUN_BC);
1891 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);
1892 if (yield) {
1893 return *self->u_gen_instance.sp;
1894 } else {
1895 if (*self->u_gen_instance.sp == py_const_none) {
1896 return py_const_stop_iteration;
1897 } else {
1898 // TODO return StopIteration with value *self->u_gen_instance.sp
1899 return py_const_stop_iteration;
1900 }
1901 }
1902
1903 } else if (IS_O(o_in, O_RANGE_IT)) {
Damience89a212013-10-15 22:25:17 +01001904 py_obj_base_t *o = o_in;
1905 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)) {
1906 py_obj_t o_out = TO_SMALL_INT(o->u_range_it.cur);
1907 o->u_range_it.cur += o->u_range_it.step;
1908 return o_out;
1909 } else {
1910 return py_const_stop_iteration;
1911 }
Damienbd254452013-10-16 20:39:12 +01001912
Damienc226dca2013-10-16 16:12:52 +01001913 } else if (IS_O(o_in, O_TUPLE_IT) || IS_O(o_in, O_LIST_IT)) {
1914 py_obj_base_t *o = o_in;
1915 if (o->u_tuple_list_it.cur < o->u_tuple_list_it.obj->u_tuple_list.len) {
1916 py_obj_t o_out = o->u_tuple_list_it.obj->u_tuple_list.items[o->u_tuple_list_it.cur];
1917 o->u_tuple_list_it.cur += 1;
1918 return o_out;
1919 } else {
1920 return py_const_stop_iteration;
1921 }
Damienbd254452013-10-16 20:39:12 +01001922
Damience89a212013-10-15 22:25:17 +01001923 } else {
1924 nlr_jump(py_obj_new_exception_2(q_TypeError, "? '%s' object is not iterable", py_obj_get_type_str(o_in), NULL));
1925 }
1926}
1927
Damiendf4b4f32013-10-19 18:28:01 +01001928void *const rt_fun_table[RT_F_NUMBER_OF] = {
Damien429d7192013-10-04 19:53:11 +01001929 rt_load_const_str,
1930 rt_load_name,
1931 rt_load_global,
Damien7f5dacf2013-10-10 11:24:39 +01001932 rt_load_build_class,
Damien429d7192013-10-04 19:53:11 +01001933 rt_load_attr,
1934 rt_load_method,
1935 rt_store_name,
Damien7f5dacf2013-10-10 11:24:39 +01001936 rt_store_attr,
Damien429d7192013-10-04 19:53:11 +01001937 rt_store_subscr,
1938 rt_is_true,
1939 rt_unary_op,
Damiend2755ec2013-10-16 23:58:48 +01001940 rt_build_tuple,
Damien429d7192013-10-04 19:53:11 +01001941 rt_build_list,
Damiend2755ec2013-10-16 23:58:48 +01001942 rt_list_append,
Damien429d7192013-10-04 19:53:11 +01001943 rt_build_map,
1944 rt_store_map,
1945 rt_build_set,
Damiend2755ec2013-10-16 23:58:48 +01001946 rt_store_set,
Damien429d7192013-10-04 19:53:11 +01001947 rt_make_function_from_id,
Damieneb19efb2013-10-10 22:06:54 +01001948 rt_call_function_n,
Damien7f5dacf2013-10-10 11:24:39 +01001949 rt_call_method_n,
Damien429d7192013-10-04 19:53:11 +01001950 rt_binary_op,
1951 rt_compare_op,
Damiend2755ec2013-10-16 23:58:48 +01001952 rt_getiter,
1953 rt_iternext,
Damien429d7192013-10-04 19:53:11 +01001954};
1955
1956/*
1957void rt_f_vector(rt_fun_kind_t fun_kind) {
1958 (rt_f_table[fun_kind])();
1959}
1960*/
Damienec63cce2013-10-22 22:58:17 +01001961
1962// temporary way of making C modules
1963// hack: use class to mimic a module
1964
Damien8b3a7c22013-10-23 20:20:17 +01001965py_obj_t py_module_new(void) {
Damienec63cce2013-10-22 22:58:17 +01001966 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1967 o->kind = O_CLASS;
1968 o->u_class.locals = py_map_new(MAP_QSTR, 0);
1969 return o;
1970}