blob: 0b76df8a5b60ae3089cccc96aa8976b21638da08 [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,
45 O_EXCEPTION_2,
46 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 {
Damiena3977762013-10-09 23:10:10 +010078 py_map_kind_t kind; // TODO merge this 1-bit field into alloc or used
Damien429d7192013-10-04 19:53:11 +010079 machine_uint_t alloc;
80 machine_uint_t used;
81 py_map_elem_t *table;
82} py_map_t;
83
Damiena3977762013-10-09 23:10:10 +010084typedef struct _py_obj_base_t py_obj_base_t;
85
86struct _py_obj_base_t {
Damien429d7192013-10-04 19:53:11 +010087 py_obj_kind_t kind;
88 union {
89 const char *id;
90 qstr u_str;
Damien3ef4abb2013-10-12 16:53:13 +010091#if MICROPY_ENABLE_FLOAT
Damiene4af64f2013-10-06 12:04:13 +010092 float_t u_flt;
Damien429d7192013-10-04 19:53:11 +010093#endif
Damience89a212013-10-15 22:25:17 +010094 struct { // for O_EXCEPTION_0
95 qstr id;
96 } u_exc0;
97 struct { // for O_EXCEPTION_2
98 // TODO reduce size or make generic object or something
99 qstr id;
100 const char *fmt;
101 const char *s1;
102 const char *s2;
103 } u_exc2;
104 struct { // for O_RANGE
105 // TODO make generic object or something
106 machine_int_t start;
107 machine_int_t stop;
108 machine_int_t step;
109 } u_range;
110 struct { // for O_RANGE_IT
111 // TODO make generic object or something
112 machine_int_t cur;
113 machine_int_t stop;
114 machine_int_t step;
115 } u_range_it;
Damien429d7192013-10-04 19:53:11 +0100116 struct { // for O_FUN_[012N]
Damien429d7192013-10-04 19:53:11 +0100117 int n_args;
Damien826005c2013-10-05 23:17:28 +0100118 void *fun;
Damien429d7192013-10-04 19:53:11 +0100119 } u_fun;
120 struct { // for O_FUN_BC
Damien826005c2013-10-05 23:17:28 +0100121 int n_args;
Damien429d7192013-10-04 19:53:11 +0100122 byte *code;
123 uint len;
Damien429d7192013-10-04 19:53:11 +0100124 } u_fun_bc;
Damien826005c2013-10-05 23:17:28 +0100125 struct { // for O_FUN_ASM
126 int n_args;
127 void *fun;
128 } u_fun_asm;
Damienbd254452013-10-16 20:39:12 +0100129 struct { // for O_GEN_WRAP
130 int n_state;
131 py_obj_base_t *fun;
132 } u_gen_wrap;
133 struct { // for O_GEN_INSTANCE
134 py_obj_t *state;
135 const byte *ip;
136 py_obj_t *sp;
137 } u_gen_instance;
Damien429d7192013-10-04 19:53:11 +0100138 struct { // for O_BOUND_METH
139 py_obj_t meth;
140 py_obj_t self;
141 } u_bound_meth;
Damienc226dca2013-10-16 16:12:52 +0100142 struct { // for O_TUPLE, O_LIST
Damien429d7192013-10-04 19:53:11 +0100143 int alloc;
144 int len;
145 py_obj_t *items;
Damienc226dca2013-10-16 16:12:52 +0100146 } u_tuple_list;
147 struct { // for O_TUPLE_IT, O_LIST_IT
148 py_obj_base_t *obj;
149 int cur;
150 } u_tuple_list_it;
Damien429d7192013-10-04 19:53:11 +0100151 struct { // for O_SET
152 int alloc;
153 int used;
154 py_obj_t *table;
155 } u_set;
156 py_map_t u_map; // for O_MAP
Damien429d7192013-10-04 19:53:11 +0100157 struct { // for O_CLASS
Damiena3977762013-10-09 23:10:10 +0100158 py_map_t *locals;
Damien429d7192013-10-04 19:53:11 +0100159 } u_class;
Damiena3977762013-10-09 23:10:10 +0100160 struct { // for O_OBJ
161 py_obj_base_t *class; // points to a O_CLASS object
162 py_map_t *members;
163 } u_obj;
Damien429d7192013-10-04 19:53:11 +0100164 };
Damiena3977762013-10-09 23:10:10 +0100165};
Damien429d7192013-10-04 19:53:11 +0100166
167py_obj_t py_const_none;
168py_obj_t py_const_false;
169py_obj_t py_const_true;
Damience89a212013-10-15 22:25:17 +0100170py_obj_t py_const_stop_iteration;
Damien429d7192013-10-04 19:53:11 +0100171
Damieneb19efb2013-10-10 22:06:54 +0100172// locals and globals need to be pointers because they can be the same in outer module scope
173py_map_t *map_locals;
174py_map_t *map_globals;
Damien429d7192013-10-04 19:53:11 +0100175py_map_t map_builtins;
176
177// approximatelly doubling primes; made with Mathematica command: Table[Prime[Floor[(1.7)^n]], {n, 3, 24}]
178static 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};
179
180int get_doubling_prime_greater_or_equal_to(int x) {
181 for (int i = 0; i < sizeof(doubling_primes) / sizeof(int); i++) {
182 if (doubling_primes[i] >= x) {
183 return doubling_primes[i];
184 }
185 }
186 // ran out of primes in the table!
187 // return something sensible, at least make it odd
188 return x | 1;
189}
190
191void py_map_init(py_map_t *map, py_map_kind_t kind, int n) {
192 map->kind = kind;
193 map->alloc = get_doubling_prime_greater_or_equal_to(n + 1);
194 map->used = 0;
195 map->table = m_new(py_map_elem_t, map->alloc);
196 for (int i = 0; i < map->alloc; i++) {
197 map->table[i].key = NULL;
198 map->table[i].value = NULL;
199 }
200}
201
202py_map_t *py_map_new(py_map_kind_t kind, int n) {
203 py_map_t *map = m_new(py_map_t, 1);
204 py_map_init(map, kind, n);
205 return map;
206}
207
208int py_obj_hash(py_obj_t o_in) {
209 if (IS_SMALL_INT(o_in)) {
210 return FROM_SMALL_INT(o_in);
211 } else if (IS_O(o_in, O_STR)) {
212 return ((py_obj_base_t*)o_in)->u_str;
213 } else {
214 assert(0);
215 return 0;
216 }
217}
218
219bool py_obj_equal(py_obj_t o1, py_obj_t o2) {
220 if (o1 == o2) {
221 return true;
222 } else if (IS_SMALL_INT(o1) && IS_SMALL_INT(o2)) {
223 return false;
224 } else if (IS_O(o1, O_STR) && IS_O(o2, O_STR)) {
225 return ((py_obj_base_t*)o1)->u_str == ((py_obj_base_t*)o2)->u_str;
226 } else {
227 assert(0);
228 return false;
229 }
230}
231
232py_map_elem_t* py_map_lookup_helper(py_map_t *map, py_obj_t index, bool add_if_not_found) {
233 bool is_map_py_obj = (map->kind == MAP_PY_OBJ);
234 machine_uint_t hash;
235 if (is_map_py_obj) {
236 hash = py_obj_hash(index);
237 } else {
238 hash = (machine_uint_t)index;
239 }
240 uint pos = hash % map->alloc;
241 for (;;) {
242 py_map_elem_t *elem = &map->table[pos];
243 if (elem->key == NULL) {
244 // not in table
245 if (add_if_not_found) {
246 if (map->used + 1 >= map->alloc) {
247 // not enough room in table, rehash it
248 int old_alloc = map->alloc;
249 py_map_elem_t *old_table = map->table;
250 map->alloc = get_doubling_prime_greater_or_equal_to(map->alloc + 1);
251 map->used = 0;
252 map->table = m_new(py_map_elem_t, map->alloc);
253 for (int i = 0; i < old_alloc; i++) {
254 if (old_table[i].key != NULL) {
255 py_map_lookup_helper(map, old_table[i].key, true)->value = old_table[i].value;
256 }
257 }
258 m_free(old_table);
259 // restart the search for the new element
260 pos = hash % map->alloc;
261 } else {
262 map->used += 1;
263 elem->key = index;
264 return elem;
265 }
266 } else {
267 return NULL;
268 }
269 } else if (elem->key == index || (is_map_py_obj && py_obj_equal(elem->key, index))) {
270 // found it
271 if (add_if_not_found) {
272 elem->key = index;
273 }
274 return elem;
275 } else {
276 // not yet found, keep searching in this table
277 pos = (pos + 1) % map->alloc;
278 }
279 }
280}
281
282py_map_elem_t* py_qstr_map_lookup(py_map_t *map, qstr index, bool add_if_not_found) {
283 py_obj_t o = (py_obj_t)(machine_uint_t)index;
284 return py_map_lookup_helper(map, o, add_if_not_found);
285}
286
287py_map_elem_t* py_map_lookup(py_obj_t o, py_obj_t index, bool add_if_not_found) {
288 assert(IS_O(o, O_MAP));
289 return py_map_lookup_helper(&((py_obj_base_t *)o)->u_map, index, add_if_not_found);
290}
291
292static bool fit_small_int(py_small_int_t o) {
293 return true;
294}
295
296py_obj_t py_obj_new_const(const char *id) {
297 py_obj_base_t *o = m_new(py_obj_base_t, 1);
298 o->kind = O_CONST;
299 o->id = id;
300 return (py_obj_t)o;
301}
302
303py_obj_t py_obj_new_str(qstr qstr) {
304 py_obj_base_t *o = m_new(py_obj_base_t, 1);
305 o->kind = O_STR;
306 o->u_str = qstr;
307 return (py_obj_t)o;
308}
309
Damien3ef4abb2013-10-12 16:53:13 +0100310#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100311py_obj_t py_obj_new_float(float_t val) {
312 py_obj_base_t *o = m_new(py_obj_base_t, 1);
313 o->kind = O_FLOAT;
Damiene4af64f2013-10-06 12:04:13 +0100314 o->u_flt = val;
Damien429d7192013-10-04 19:53:11 +0100315 return (py_obj_t)o;
316}
317#endif
318
Damience89a212013-10-15 22:25:17 +0100319py_obj_t py_obj_new_exception_0(qstr id) {
320 py_obj_base_t *o = m_new(py_obj_base_t, 1);
321 o->kind = O_EXCEPTION_0;
322 o->u_exc0.id = id;
323 return (py_obj_t)o;
324}
325
326py_obj_t py_obj_new_exception_2(qstr id, const char *fmt, const char *s1, const char *s2) {
327 py_obj_base_t *o = m_new(py_obj_base_t, 1);
328 o->kind = O_EXCEPTION_2;
329 o->u_exc2.id = id;
330 o->u_exc2.fmt = fmt;
331 o->u_exc2.s1 = s1;
332 o->u_exc2.s2 = s2;
333 return (py_obj_t)o;
334}
335
336// range is a class and instances are immutable sequence objects
337py_obj_t py_obj_new_range(int start, int stop, int step) {
338 py_obj_base_t *o = m_new(py_obj_base_t, 1);
339 o->kind = O_RANGE;
340 o->u_range.start = start;
341 o->u_range.stop = stop;
342 o->u_range.step = step;
343 return o;
344}
345
346py_obj_t py_obj_new_range_iterator(int cur, int stop, int step) {
347 py_obj_base_t *o = m_new(py_obj_base_t, 1);
348 o->kind = O_RANGE_IT;
349 o->u_range_it.cur = cur;
350 o->u_range_it.stop = stop;
351 o->u_range_it.step = step;
352 return o;
353}
354
Damienc226dca2013-10-16 16:12:52 +0100355py_obj_t py_obj_new_tuple_iterator(py_obj_base_t *tuple, int cur) {
356 py_obj_base_t *o = m_new(py_obj_base_t, 1);
357 o->kind = O_TUPLE_IT;
358 o->u_tuple_list_it.obj = tuple;
359 o->u_tuple_list_it.cur = cur;
360 return o;
361}
362
363py_obj_t py_obj_new_list_iterator(py_obj_base_t *list, int cur) {
364 py_obj_base_t *o = m_new(py_obj_base_t, 1);
365 o->kind = O_LIST_IT;
366 o->u_tuple_list_it.obj = list;
367 o->u_tuple_list_it.cur = cur;
368 return o;
369}
370
371py_obj_t rt_list_append(py_obj_t self_in, py_obj_t arg) {
Damien429d7192013-10-04 19:53:11 +0100372 assert(IS_O(self_in, O_LIST));
373 py_obj_base_t *self = self_in;
Damienc226dca2013-10-16 16:12:52 +0100374 if (self->u_tuple_list.len >= self->u_tuple_list.alloc) {
375 self->u_tuple_list.alloc *= 2;
376 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 +0100377 }
Damienc226dca2013-10-16 16:12:52 +0100378 self->u_tuple_list.items[self->u_tuple_list.len++] = arg;
Damien429d7192013-10-04 19:53:11 +0100379 return arg;
380}
381
Damienbd254452013-10-16 20:39:12 +0100382py_obj_t rt_gen_instance_next(py_obj_t self_in) {
383 py_obj_t ret = rt_iternext(self_in);
384 if (ret == py_const_stop_iteration) {
385 nlr_jump(py_obj_new_exception_0(qstr_from_str_static("StopIteration")));
386 } else {
387 return ret;
388 }
389}
390
Damien429d7192013-10-04 19:53:11 +0100391static qstr q_append;
392static qstr q_print;
393static qstr q_len;
394static qstr q___build_class__;
Damienbd254452013-10-16 20:39:12 +0100395static qstr q___next__;
Damience89a212013-10-15 22:25:17 +0100396static qstr q_AttributeError;
Damienc226dca2013-10-16 16:12:52 +0100397static qstr q_IndexError;
Damience89a212013-10-15 22:25:17 +0100398static qstr q_NameError;
399static qstr q_TypeError;
Damien429d7192013-10-04 19:53:11 +0100400
401typedef enum {
Damien826005c2013-10-05 23:17:28 +0100402 PY_CODE_NONE,
Damien429d7192013-10-04 19:53:11 +0100403 PY_CODE_BYTE,
Damien826005c2013-10-05 23:17:28 +0100404 PY_CODE_NATIVE,
405 PY_CODE_INLINE_ASM,
Damien429d7192013-10-04 19:53:11 +0100406} py_code_kind_t;
407
408typedef struct _py_code_t {
409 py_code_kind_t kind;
410 int n_args;
Damienbd254452013-10-16 20:39:12 +0100411 int n_locals;
412 int n_stack;
413 bool is_generator;
Damien429d7192013-10-04 19:53:11 +0100414 union {
415 struct {
Damien429d7192013-10-04 19:53:11 +0100416 byte *code;
417 uint len;
418 } u_byte;
Damien826005c2013-10-05 23:17:28 +0100419 struct {
420 py_fun_t fun;
421 } u_native;
422 struct {
Damiene4af64f2013-10-06 12:04:13 +0100423 void *fun;
Damien826005c2013-10-05 23:17:28 +0100424 } u_inline_asm;
Damien429d7192013-10-04 19:53:11 +0100425 };
426} py_code_t;
427
428static int next_unique_code_id;
429static py_code_t *unique_codes;
430
431py_obj_t fun_list_append;
Damienbd254452013-10-16 20:39:12 +0100432py_obj_t fun_gen_instance_next;
Damien429d7192013-10-04 19:53:11 +0100433
434py_obj_t py_builtin_print(py_obj_t o) {
435 if (IS_O(o, O_STR)) {
436 // special case, print string raw
437 printf("%s\n", qstr_str(((py_obj_base_t*)o)->u_str));
438 } else {
439 // print the object Python style
440 py_obj_print(o);
441 printf("\n");
442 }
443 return py_const_none;
444}
445
446py_obj_t py_builtin_len(py_obj_t o_in) {
447 py_small_int_t len = 0;
Damienc226dca2013-10-16 16:12:52 +0100448 if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) {
Damien429d7192013-10-04 19:53:11 +0100449 py_obj_base_t *o = o_in;
Damienc226dca2013-10-16 16:12:52 +0100450 len = o->u_tuple_list.len;
Damien429d7192013-10-04 19:53:11 +0100451 } else if (IS_O(o_in, O_MAP)) {
452 py_obj_base_t *o = o_in;
453 len = o->u_map.used;
454 } else {
455 assert(0);
456 }
457 return TO_SMALL_INT(len);
458}
459
Damiena3977762013-10-09 23:10:10 +0100460py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name) {
461 // we differ from CPython: we set the new __locals__ object here
Damieneb19efb2013-10-10 22:06:54 +0100462 py_map_t *old_locals = map_locals;
Damiena3977762013-10-09 23:10:10 +0100463 py_map_t *class_locals = py_map_new(MAP_QSTR, 0);
Damieneb19efb2013-10-10 22:06:54 +0100464 map_locals = class_locals;
Damiena3977762013-10-09 23:10:10 +0100465
466 // call the class code
467 rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef);
468
469 // restore old __locals__ object
470 map_locals = old_locals;
471
472 // create and return the new class
Damien429d7192013-10-04 19:53:11 +0100473 py_obj_base_t *o = m_new(py_obj_base_t, 1);
474 o->kind = O_CLASS;
Damiena3977762013-10-09 23:10:10 +0100475 o->u_class.locals = class_locals;
Damien429d7192013-10-04 19:53:11 +0100476 return o;
477}
478
Damience89a212013-10-15 22:25:17 +0100479py_obj_t py_builtin_range(py_obj_t o_arg) {
480 return py_obj_new_range(0, rt_get_int(o_arg), 1);
481}
482
Damiena1ddfcc2013-10-10 23:25:50 +0100483#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100484FILE *fp_native = NULL;
Damiena1ddfcc2013-10-10 23:25:50 +0100485#endif
Damien429d7192013-10-04 19:53:11 +0100486
487void rt_init() {
488 q_append = qstr_from_str_static("append");
489 q_print = qstr_from_str_static("print");
490 q_len = qstr_from_str_static("len");
491 q___build_class__ = qstr_from_str_static("__build_class__");
Damienbd254452013-10-16 20:39:12 +0100492 q___next__ = qstr_from_str_static("__next__");
Damience89a212013-10-15 22:25:17 +0100493 q_AttributeError = qstr_from_str_static("AttributeError");
Damienc226dca2013-10-16 16:12:52 +0100494 q_IndexError = qstr_from_str_static("IndexError");
Damience89a212013-10-15 22:25:17 +0100495 q_NameError = qstr_from_str_static("NameError");
496 q_TypeError = qstr_from_str_static("TypeError");
Damien429d7192013-10-04 19:53:11 +0100497
498 py_const_none = py_obj_new_const("None");
499 py_const_false = py_obj_new_const("False");
500 py_const_true = py_obj_new_const("True");
Damience89a212013-10-15 22:25:17 +0100501 py_const_stop_iteration = py_obj_new_const("StopIteration");
Damien429d7192013-10-04 19:53:11 +0100502
Damieneb19efb2013-10-10 22:06:54 +0100503 // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
504 map_locals = map_globals = py_map_new(MAP_QSTR, 1);
505 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 +0100506
507 py_map_init(&map_builtins, MAP_QSTR, 3);
508 py_qstr_map_lookup(&map_builtins, q_print, true)->value = rt_make_function_1(py_builtin_print);
509 py_qstr_map_lookup(&map_builtins, q_len, true)->value = rt_make_function_1(py_builtin_len);
510 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 +0100511 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 +0100512
513 next_unique_code_id = 1;
514 unique_codes = NULL;
515
Damienc226dca2013-10-16 16:12:52 +0100516 fun_list_append = rt_make_function_2(rt_list_append);
Damienbd254452013-10-16 20:39:12 +0100517 fun_gen_instance_next = rt_make_function_1(rt_gen_instance_next);
Damien429d7192013-10-04 19:53:11 +0100518
Damiena1ddfcc2013-10-10 23:25:50 +0100519#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100520 fp_native = fopen("out-native", "wb");
Damiena1ddfcc2013-10-10 23:25:50 +0100521#endif
Damien429d7192013-10-04 19:53:11 +0100522}
523
524void rt_deinit() {
Damiena1ddfcc2013-10-10 23:25:50 +0100525#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100526 if (fp_native != NULL) {
527 fclose(fp_native);
528 }
Damiena1ddfcc2013-10-10 23:25:50 +0100529#endif
Damien429d7192013-10-04 19:53:11 +0100530}
531
532int rt_get_new_unique_code_id() {
533 return next_unique_code_id++;
534}
535
Damien826005c2013-10-05 23:17:28 +0100536static void alloc_unique_codes() {
Damien429d7192013-10-04 19:53:11 +0100537 if (unique_codes == NULL) {
538 unique_codes = m_new(py_code_t, next_unique_code_id);
Damien826005c2013-10-05 23:17:28 +0100539 for (int i = 0; i < next_unique_code_id; i++) {
540 unique_codes[i].kind = PY_CODE_NONE;
541 }
Damien429d7192013-10-04 19:53:11 +0100542 }
Damien826005c2013-10-05 23:17:28 +0100543}
544
Damienbd254452013-10-16 20:39:12 +0100545void 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 +0100546 alloc_unique_codes();
547
548 assert(unique_code_id < next_unique_code_id);
549 unique_codes[unique_code_id].kind = PY_CODE_BYTE;
550 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +0100551 unique_codes[unique_code_id].n_locals = n_locals;
552 unique_codes[unique_code_id].n_stack = n_stack;
553 unique_codes[unique_code_id].is_generator = is_generator;
Damien826005c2013-10-05 23:17:28 +0100554 unique_codes[unique_code_id].u_byte.code = code;
555 unique_codes[unique_code_id].u_byte.len = len;
556
557 DEBUG_printf("assign byte code: id=%d code=%p len=%u n_args=%d\n", unique_code_id, code, len, n_args);
558}
559
560void rt_assign_native_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
561 alloc_unique_codes();
562
Damienb05d7072013-10-05 13:37:10 +0100563 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
Damien429d7192013-10-04 19:53:11 +0100564 unique_codes[unique_code_id].kind = PY_CODE_NATIVE;
565 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +0100566 unique_codes[unique_code_id].n_locals = 0;
567 unique_codes[unique_code_id].n_stack = 0;
568 unique_codes[unique_code_id].is_generator = false;
Damien429d7192013-10-04 19:53:11 +0100569 unique_codes[unique_code_id].u_native.fun = fun;
570
Damiena1ddfcc2013-10-10 23:25:50 +0100571#ifdef DEBUG_PRINT
Damien429d7192013-10-04 19:53:11 +0100572 DEBUG_printf("assign native code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
573 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
574 for (int i = 0; i < 128 && i < len; i++) {
575 if (i > 0 && i % 16 == 0) {
576 DEBUG_printf("\n");
577 }
578 DEBUG_printf(" %02x", fun_data[i]);
579 }
580 DEBUG_printf("\n");
581
Damiena1ddfcc2013-10-10 23:25:50 +0100582#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100583 if (fp_native != NULL) {
584 fwrite(fun_data, len, 1, fp_native);
Damien13ed3a62013-10-08 09:05:10 +0100585 fflush(fp_native);
Damien429d7192013-10-04 19:53:11 +0100586 }
Damiena1ddfcc2013-10-10 23:25:50 +0100587#endif
588#endif
Damien429d7192013-10-04 19:53:11 +0100589}
590
Damien826005c2013-10-05 23:17:28 +0100591void rt_assign_inline_asm_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
592 alloc_unique_codes();
Damien429d7192013-10-04 19:53:11 +0100593
Damien826005c2013-10-05 23:17:28 +0100594 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
595 unique_codes[unique_code_id].kind = PY_CODE_INLINE_ASM;
596 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +0100597 unique_codes[unique_code_id].n_locals = 0;
598 unique_codes[unique_code_id].n_stack = 0;
599 unique_codes[unique_code_id].is_generator = false;
Damien826005c2013-10-05 23:17:28 +0100600 unique_codes[unique_code_id].u_inline_asm.fun = fun;
601
Damiena1ddfcc2013-10-10 23:25:50 +0100602#ifdef DEBUG_PRINT
Damien826005c2013-10-05 23:17:28 +0100603 DEBUG_printf("assign inline asm code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
604 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
605 for (int i = 0; i < 128 && i < len; i++) {
606 if (i > 0 && i % 16 == 0) {
607 DEBUG_printf("\n");
608 }
609 DEBUG_printf(" %02x", fun_data[i]);
610 }
611 DEBUG_printf("\n");
612
Damiena1ddfcc2013-10-10 23:25:50 +0100613#ifdef WRITE_NATIVE
Damien826005c2013-10-05 23:17:28 +0100614 if (fp_native != NULL) {
615 fwrite(fun_data, len, 1, fp_native);
616 }
Damiena1ddfcc2013-10-10 23:25:50 +0100617#endif
618#endif
Damien429d7192013-10-04 19:53:11 +0100619}
620
Damiena3977762013-10-09 23:10:10 +0100621bool py_obj_is_callable(py_obj_t o_in) {
622 if (IS_SMALL_INT(o_in)) {
623 return false;
624 } else {
625 py_obj_base_t *o = o_in;
626 switch (o->kind) {
627 case O_FUN_0:
628 case O_FUN_1:
629 case O_FUN_2:
630 case O_FUN_N:
631 case O_FUN_BC:
632 case O_FUN_ASM:
Damieneb19efb2013-10-10 22:06:54 +0100633 // what about O_CLASS, and an O_OBJ that has a __call__ method?
Damiena3977762013-10-09 23:10:10 +0100634 return true;
635 default:
636 return false;
637 }
638 }
639}
640
Damien429d7192013-10-04 19:53:11 +0100641const char *py_obj_get_type_str(py_obj_t o_in) {
642 if (IS_SMALL_INT(o_in)) {
643 return "int";
644 } else {
645 py_obj_base_t *o = o_in;
646 switch (o->kind) {
647 case O_CONST:
648 if (o == py_const_none) {
649 return "NoneType";
650 } else {
651 return "bool";
652 }
653 case O_STR:
654 return "str";
Damien3ef4abb2013-10-12 16:53:13 +0100655#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100656 case O_FLOAT:
657 return "float";
658#endif
Damien6cdd3af2013-10-05 18:08:26 +0100659 case O_FUN_0:
660 case O_FUN_1:
661 case O_FUN_2:
662 case O_FUN_N:
663 case O_FUN_BC:
664 return "function";
Damienbd254452013-10-16 20:39:12 +0100665 case O_GEN_INSTANCE:
666 return "generator";
Damienc226dca2013-10-16 16:12:52 +0100667 case O_TUPLE:
668 return "tuple";
Damien429d7192013-10-04 19:53:11 +0100669 case O_LIST:
670 return "list";
Damienc226dca2013-10-16 16:12:52 +0100671 case O_TUPLE_IT:
672 return "tuple_iterator";
673 case O_LIST_IT:
674 return "list_iterator";
Damien429d7192013-10-04 19:53:11 +0100675 case O_SET:
676 return "set";
677 case O_MAP:
678 return "dict";
Damiena3977762013-10-09 23:10:10 +0100679 case O_OBJ:
680 {
681 py_map_elem_t *qn = py_qstr_map_lookup(o->u_obj.class->u_class.locals, qstr_from_str_static("__qualname__"), false);
682 assert(qn != NULL);
683 assert(IS_O(qn->value, O_STR));
684 return qstr_str(((py_obj_base_t*)qn->value)->u_str);
685 }
Damien429d7192013-10-04 19:53:11 +0100686 default:
687 assert(0);
688 return "UnknownType";
689 }
690 }
691}
692
693void py_obj_print(py_obj_t o_in) {
694 if (IS_SMALL_INT(o_in)) {
695 printf("%d", (int)FROM_SMALL_INT(o_in));
696 } else {
697 py_obj_base_t *o = o_in;
698 switch (o->kind) {
699 case O_CONST:
700 printf("%s", o->id);
701 break;
702 case O_STR:
703 // TODO need to escape chars etc
704 printf("'%s'", qstr_str(o->u_str));
705 break;
Damien3ef4abb2013-10-12 16:53:13 +0100706#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100707 case O_FLOAT:
Damiene4af64f2013-10-06 12:04:13 +0100708 printf("%f", o->u_flt);
Damien429d7192013-10-04 19:53:11 +0100709 break;
710#endif
Damienbd254452013-10-16 20:39:12 +0100711 case O_EXCEPTION_0:
712 printf("%s", qstr_str(o->u_exc0.id));
713 break;
Damience89a212013-10-15 22:25:17 +0100714 case O_EXCEPTION_2:
715 printf("%s: ", qstr_str(o->u_exc2.id));
716 printf(o->u_exc2.fmt, o->u_exc2.s1, o->u_exc2.s2);
717 break;
Damienbd254452013-10-16 20:39:12 +0100718 case O_GEN_INSTANCE:
719 printf("<generator object 'fun-name' at %p>", o);
720 break;
Damienc226dca2013-10-16 16:12:52 +0100721 case O_TUPLE:
722 printf("(");
723 for (int i = 0; i < o->u_tuple_list.len; i++) {
Damien429d7192013-10-04 19:53:11 +0100724 if (i > 0) {
725 printf(", ");
726 }
Damienc226dca2013-10-16 16:12:52 +0100727 py_obj_print(o->u_tuple_list.items[i]);
728 }
729 if (o->u_tuple_list.len == 1) {
730 printf(",");
731 }
732 printf(")");
733 break;
734 case O_LIST:
735 printf("[");
736 for (int i = 0; i < o->u_tuple_list.len; i++) {
737 if (i > 0) {
738 printf(", ");
739 }
740 py_obj_print(o->u_tuple_list.items[i]);
Damien429d7192013-10-04 19:53:11 +0100741 }
742 printf("]");
743 break;
744 case O_SET:
745 {
746 bool first = true;
747 printf("{");
748 for (int i = 0; i < o->u_set.alloc; i++) {
749 if (o->u_set.table[i] != NULL) {
750 if (!first) {
751 printf(", ");
752 }
753 first = false;
754 py_obj_print(o->u_set.table[i]);
755 }
756 }
757 printf("}");
758 break;
759 }
760 case O_MAP:
761 {
762 bool first = true;
763 printf("{");
764 for (int i = 0; i < o->u_map.alloc; i++) {
765 if (o->u_map.table[i].key != NULL) {
766 if (!first) {
767 printf(", ");
768 }
769 first = false;
770 py_obj_print(o->u_map.table[i].key);
771 printf(": ");
772 py_obj_print(o->u_map.table[i].value);
773 }
774 }
775 printf("}");
776 break;
777 }
778 default:
Damiena3977762013-10-09 23:10:10 +0100779 printf("<? %d>", o->kind);
Damien429d7192013-10-04 19:53:11 +0100780 assert(0);
781 }
782 }
783}
784
785int rt_is_true(py_obj_t arg) {
786 DEBUG_OP_printf("is true %p\n", arg);
787 if (IS_SMALL_INT(arg)) {
788 if (FROM_SMALL_INT(arg) == 0) {
789 return 0;
790 } else {
791 return 1;
792 }
793 } else if (arg == py_const_none) {
794 return 0;
795 } else if (arg == py_const_false) {
796 return 0;
797 } else if (arg == py_const_true) {
798 return 1;
799 } else {
800 assert(0);
801 return 0;
802 }
803}
804
805int rt_get_int(py_obj_t arg) {
Damienc226dca2013-10-16 16:12:52 +0100806 if (arg == py_const_false) {
807 return 0;
808 } else if (arg == py_const_true) {
809 return 1;
810 } else if (IS_SMALL_INT(arg)) {
Damien429d7192013-10-04 19:53:11 +0100811 return FROM_SMALL_INT(arg);
812 } else {
813 assert(0);
814 return 0;
815 }
816}
817
818py_obj_t rt_load_const_str(qstr qstr) {
819 DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
820 return py_obj_new_str(qstr);
821}
822
823py_obj_t rt_load_name(qstr qstr) {
824 // logic: search locals, globals, builtins
Damiena3977762013-10-09 23:10:10 +0100825 DEBUG_OP_printf("load name %s\n", qstr_str(qstr));
Damieneb19efb2013-10-10 22:06:54 +0100826 py_map_elem_t *elem = py_qstr_map_lookup(map_locals, qstr, false);
Damiena3977762013-10-09 23:10:10 +0100827 if (elem == NULL) {
Damieneb19efb2013-10-10 22:06:54 +0100828 elem = py_qstr_map_lookup(map_globals, qstr, false);
Damiena3977762013-10-09 23:10:10 +0100829 if (elem == NULL) {
830 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
831 if (elem == NULL) {
Damience89a212013-10-15 22:25:17 +0100832 nlr_jump(py_obj_new_exception_2(q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL));
Damiena3977762013-10-09 23:10:10 +0100833 }
834 }
835 }
836 return elem->value;
837}
838
839py_obj_t rt_load_global(qstr qstr) {
840 // logic: search globals, builtins
841 DEBUG_OP_printf("load global %s\n", qstr_str(qstr));
Damieneb19efb2013-10-10 22:06:54 +0100842 py_map_elem_t *elem = py_qstr_map_lookup(map_globals, qstr, false);
Damien429d7192013-10-04 19:53:11 +0100843 if (elem == NULL) {
844 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
845 if (elem == NULL) {
Damience89a212013-10-15 22:25:17 +0100846 nlr_jump(py_obj_new_exception_2(q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL));
Damien429d7192013-10-04 19:53:11 +0100847 }
848 }
849 return elem->value;
850}
851
Damien429d7192013-10-04 19:53:11 +0100852py_obj_t rt_load_build_class() {
853 DEBUG_OP_printf("load_build_class\n");
854 py_map_elem_t *elem = py_qstr_map_lookup(&map_builtins, q___build_class__, false);
855 if (elem == NULL) {
856 printf("name doesn't exist: __build_class__\n");
857 assert(0);
858 }
859 return elem->value;
860}
861
862void rt_store_name(qstr qstr, py_obj_t obj) {
Damiena3977762013-10-09 23:10:10 +0100863 DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qstr), obj);
Damieneb19efb2013-10-10 22:06:54 +0100864 py_qstr_map_lookup(map_locals, qstr, true)->value = obj;
Damiena3977762013-10-09 23:10:10 +0100865}
866
867void rt_store_global(qstr qstr, py_obj_t obj) {
868 DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qstr), obj);
Damieneb19efb2013-10-10 22:06:54 +0100869 py_qstr_map_lookup(map_globals, qstr, true)->value = obj;
Damien429d7192013-10-04 19:53:11 +0100870}
871
872py_obj_t rt_unary_op(int op, py_obj_t arg) {
873 assert(0);
874 return py_const_none;
875}
876
Damienc226dca2013-10-16 16:12:52 +0100877uint get_index(py_obj_base_t *base, py_obj_t index) {
878 // assumes base is O_TUPLE or O_LIST
879 // TODO False and True are considered 0 and 1 for indexing purposes
880 int len = base->u_tuple_list.len;
881 if (IS_SMALL_INT(index)) {
882 int i = FROM_SMALL_INT(index);
883 if (i < 0) {
884 i += len;
885 }
886 if (i < 0 || i >= len) {
887 nlr_jump(py_obj_new_exception_2(q_IndexError, "%s index out of range", py_obj_get_type_str(base), NULL));
888 }
889 return i;
890 } else {
891 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)));
892 }
893}
894
Damien429d7192013-10-04 19:53:11 +0100895py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs) {
896 DEBUG_OP_printf("binary %d %p %p\n", op, lhs, rhs);
897 if (op == RT_BINARY_OP_SUBSCR) {
Damienc226dca2013-10-16 16:12:52 +0100898 if ((IS_O(lhs, O_TUPLE) || IS_O(lhs, O_LIST))) {
899 uint index = get_index(lhs, rhs);
900 return ((py_obj_base_t*)lhs)->u_tuple_list.items[index];
Damien429d7192013-10-04 19:53:11 +0100901 } else {
902 assert(0);
903 }
904 } else if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
905 py_small_int_t val;
906 switch (op) {
907 case RT_BINARY_OP_ADD:
908 case RT_BINARY_OP_INPLACE_ADD: val = FROM_SMALL_INT(lhs) + FROM_SMALL_INT(rhs); break;
Damienbd254452013-10-16 20:39:12 +0100909 case RT_BINARY_OP_SUBTRACT:
910 case RT_BINARY_OP_INPLACE_SUBTRACT: val = FROM_SMALL_INT(lhs) - FROM_SMALL_INT(rhs); break;
Damien429d7192013-10-04 19:53:11 +0100911 case RT_BINARY_OP_MULTIPLY: val = FROM_SMALL_INT(lhs) * FROM_SMALL_INT(rhs); break;
912 case RT_BINARY_OP_FLOOR_DIVIDE: val = FROM_SMALL_INT(lhs) / FROM_SMALL_INT(rhs); break;
Damien3ef4abb2013-10-12 16:53:13 +0100913#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100914 case RT_BINARY_OP_TRUE_DIVIDE: return py_obj_new_float((float_t)FROM_SMALL_INT(lhs) / (float_t)FROM_SMALL_INT(rhs));
915#endif
916 default: printf("%d\n", op); assert(0); val = 0;
917 }
918 if (fit_small_int(val)) {
919 return TO_SMALL_INT(val);
920 }
921 } else if (IS_O(lhs, O_STR) && IS_O(rhs, O_STR)) {
922 const char *lhs_str = qstr_str(((py_obj_base_t*)lhs)->u_str);
923 const char *rhs_str = qstr_str(((py_obj_base_t*)rhs)->u_str);
924 char *val;
925 switch (op) {
926 case RT_BINARY_OP_ADD:
927 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;
928 default: printf("%d\n", op); assert(0); val = NULL;
929 }
930 return py_obj_new_str(qstr_from_str_take(val));
931 }
932 assert(0);
933 return py_const_none;
934}
935
936py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs) {
937 DEBUG_OP_printf("compare %d %p %p\n", op, lhs, rhs);
938 if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
939 int cmp;
940 switch (op) {
941 case RT_COMPARE_OP_LESS: cmp = FROM_SMALL_INT(lhs) < FROM_SMALL_INT(rhs); break;
942 case RT_COMPARE_OP_MORE: cmp = FROM_SMALL_INT(lhs) > FROM_SMALL_INT(rhs); break;
943 default: assert(0); cmp = 0;
944 }
945 if (cmp) {
946 return py_const_true;
947 } else {
948 return py_const_false;
949 }
950 }
951 assert(0);
952 return py_const_none;
953}
954
955py_obj_t rt_make_function_from_id(int unique_code_id) {
Damienb05d7072013-10-05 13:37:10 +0100956 DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id);
957 if (unique_code_id < 1 || unique_code_id >= next_unique_code_id) {
Damien429d7192013-10-04 19:53:11 +0100958 // illegal code id
959 return py_const_none;
960 }
961 py_code_t *c = &unique_codes[unique_code_id];
962 py_obj_base_t *o = m_new(py_obj_base_t, 1);
963 switch (c->kind) {
Damien826005c2013-10-05 23:17:28 +0100964 case PY_CODE_BYTE:
965 o->kind = O_FUN_BC;
966 o->u_fun_bc.n_args = c->n_args;
967 o->u_fun_bc.code = c->u_byte.code;
968 o->u_fun_bc.len = c->u_byte.len;
969 break;
Damien429d7192013-10-04 19:53:11 +0100970 case PY_CODE_NATIVE:
971 switch (c->n_args) {
972 case 0: o->kind = O_FUN_0; break;
973 case 1: o->kind = O_FUN_1; break;
974 case 2: o->kind = O_FUN_2; break;
975 default: assert(0);
976 }
977 o->u_fun.fun = c->u_native.fun;
978 break;
Damien826005c2013-10-05 23:17:28 +0100979 case PY_CODE_INLINE_ASM:
980 o->kind = O_FUN_ASM;
981 o->u_fun_asm.n_args = c->n_args;
982 o->u_fun_asm.fun = c->u_inline_asm.fun;
Damien429d7192013-10-04 19:53:11 +0100983 break;
984 default:
985 assert(0);
986 }
Damienbd254452013-10-16 20:39:12 +0100987
988 // check for generator functions and if so wrap in generator object
989 if (c->is_generator) {
990 py_obj_base_t *o2 = m_new(py_obj_base_t, 1);
991 o2->kind = O_GEN_WRAP;
992 // we have at least 3 locals so the bc can write back fast[0,1,2] safely; should improve how this is done
993 o2->u_gen_wrap.n_state = (c->n_locals < 3 ? 3 : c->n_locals) + c->n_stack;
994 o2->u_gen_wrap.fun = o;
995 o = o2;
996 }
997
Damien429d7192013-10-04 19:53:11 +0100998 return o;
999}
1000
1001py_obj_t rt_make_function_0(py_fun_0_t fun) {
1002 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1003 o->kind = O_FUN_0;
1004 o->u_fun.fun = fun;
1005 return o;
1006}
1007
1008py_obj_t rt_make_function_1(py_fun_1_t fun) {
1009 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1010 o->kind = O_FUN_1;
1011 o->u_fun.fun = fun;
1012 return o;
1013}
1014
1015py_obj_t rt_make_function_2(py_fun_2_t fun) {
1016 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1017 o->kind = O_FUN_2;
1018 o->u_fun.fun = fun;
1019 return o;
1020}
1021
1022py_obj_t rt_make_function(int n_args, py_fun_t code) {
1023 // assumes code is a pointer to a py_fun_t (i think this is safe...)
1024 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1025 o->kind = O_FUN_N;
Damien429d7192013-10-04 19:53:11 +01001026 o->u_fun.n_args = n_args;
Damien826005c2013-10-05 23:17:28 +01001027 o->u_fun.fun = code;
Damien429d7192013-10-04 19:53:11 +01001028 return o;
1029}
1030
Damieneb19efb2013-10-10 22:06:54 +01001031py_obj_t rt_call_function_0(py_obj_t fun) {
1032 return rt_call_function_n(fun, 0, NULL);
1033}
1034
1035py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) {
1036 return rt_call_function_n(fun, 1, &arg);
1037}
1038
1039py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) {
1040 py_obj_t args[2];
1041 args[1] = arg1;
1042 args[0] = arg2;
1043 return rt_call_function_n(fun, 2, args);
1044}
1045
1046typedef machine_uint_t (*inline_asm_fun_0_t)();
1047typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t);
1048typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t);
1049typedef machine_uint_t (*inline_asm_fun_3_t)(machine_uint_t, machine_uint_t, machine_uint_t);
1050
Damiene4af64f2013-10-06 12:04:13 +01001051// convert a Python object to a sensible value for inline asm
1052machine_uint_t rt_convert_obj_for_inline_asm(py_obj_t obj) {
1053 // TODO for byte_array, pass pointer to the array
1054 if (IS_SMALL_INT(obj)) {
1055 return FROM_SMALL_INT(obj);
1056 } else if (obj == py_const_none) {
1057 return 0;
1058 } else if (obj == py_const_false) {
1059 return 0;
1060 } else if (obj == py_const_true) {
1061 return 1;
1062 } else {
1063 py_obj_base_t *o = obj;
1064 switch (o->kind) {
1065 case O_STR:
1066 // pointer to the string (it's probably constant though!)
1067 return (machine_uint_t)qstr_str(o->u_str);
1068
Damien3ef4abb2013-10-12 16:53:13 +01001069#if MICROPY_ENABLE_FLOAT
Damiene4af64f2013-10-06 12:04:13 +01001070 case O_FLOAT:
1071 // convert float to int (could also pass in float registers)
1072 return (machine_int_t)o->u_flt;
Damienc025ebb2013-10-12 14:30:21 +01001073#endif
Damiene4af64f2013-10-06 12:04:13 +01001074
Damienc226dca2013-10-16 16:12:52 +01001075 case O_TUPLE:
Damiene4af64f2013-10-06 12:04:13 +01001076 case O_LIST:
Damienc226dca2013-10-16 16:12:52 +01001077 // pointer to start of tuple/list (could pass length, but then could use len(x) for that)
1078 return (machine_uint_t)o->u_tuple_list.items;
Damiene4af64f2013-10-06 12:04:13 +01001079
1080 default:
1081 // just pass along a pointer to the object
1082 return (machine_uint_t)obj;
1083 }
1084 }
1085}
1086
1087// convert a return value from inline asm to a sensible Python object
1088py_obj_t rt_convert_val_from_inline_asm(machine_uint_t val) {
1089 return TO_SMALL_INT(val);
1090}
1091
Damieneb19efb2013-10-10 22:06:54 +01001092// args are in reverse order in the array
1093py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args) {
1094 int n_args_fun = 0;
Damien429d7192013-10-04 19:53:11 +01001095 if (IS_O(fun, O_FUN_0)) {
1096 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001097 if (n_args != 0) {
1098 n_args_fun = 0;
1099 goto bad_n_args;
1100 }
1101 DEBUG_OP_printf("calling native %p()\n", o->u_fun.fun);
Damien429d7192013-10-04 19:53:11 +01001102 return ((py_fun_0_t)o->u_fun.fun)();
Damieneb19efb2013-10-10 22:06:54 +01001103
1104 } else if (IS_O(fun, O_FUN_1)) {
1105 py_obj_base_t *o = fun;
1106 if (n_args != 1) {
1107 n_args_fun = 1;
1108 goto bad_n_args;
1109 }
1110 DEBUG_OP_printf("calling native %p(%p)\n", o->u_fun.fun, args[0]);
1111 return ((py_fun_1_t)o->u_fun.fun)(args[0]);
1112
1113 } else if (IS_O(fun, O_FUN_2)) {
1114 py_obj_base_t *o = fun;
1115 if (n_args != 2) {
1116 n_args_fun = 2;
1117 goto bad_n_args;
1118 }
1119 DEBUG_OP_printf("calling native %p(%p, %p)\n", o->u_fun.fun, args[1], args[0]);
1120 return ((py_fun_2_t)o->u_fun.fun)(args[1], args[0]);
1121
1122 // TODO O_FUN_N
1123
Damien429d7192013-10-04 19:53:11 +01001124 } else if (IS_O(fun, O_FUN_BC)) {
1125 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001126 if (n_args != o->u_fun_bc.n_args) {
1127 n_args_fun = o->u_fun_bc.n_args;
1128 goto bad_n_args;
1129 }
1130 DEBUG_OP_printf("calling byte code %p(n_args=%d)\n", o->u_fun_bc.code, n_args);
Damienbd254452013-10-16 20:39:12 +01001131 return py_execute_byte_code(o->u_fun_bc.code, args, n_args);
Damieneb19efb2013-10-10 22:06:54 +01001132
Damiene4af64f2013-10-06 12:04:13 +01001133 } else if (IS_O(fun, O_FUN_ASM)) {
1134 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001135 if (n_args != o->u_fun_asm.n_args) {
1136 n_args_fun = o->u_fun_asm.n_args;
1137 goto bad_n_args;
1138 }
1139 DEBUG_OP_printf("calling inline asm %p(n_args=%d)\n", o->u_fun_asm.fun, n_args);
1140 machine_uint_t ret;
1141 if (n_args == 0) {
1142 ret = ((inline_asm_fun_0_t)o->u_fun_asm.fun)();
1143 } else if (n_args == 1) {
1144 ret = ((inline_asm_fun_1_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[0]));
1145 } else if (n_args == 2) {
1146 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]));
1147 } else if (n_args == 3) {
1148 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]));
1149 } else {
1150 assert(0);
1151 ret = 0;
1152 }
1153 return rt_convert_val_from_inline_asm(ret);
1154
Damienbd254452013-10-16 20:39:12 +01001155 } else if (IS_O(fun, O_GEN_WRAP)) {
1156 py_obj_base_t *o = fun;
1157 py_obj_base_t *o_fun = o->u_gen_wrap.fun;
1158 assert(o_fun->kind == O_FUN_BC); // TODO
1159 if (n_args != o_fun->u_fun_bc.n_args) {
1160 n_args_fun = o_fun->u_fun_bc.n_args;
1161 goto bad_n_args;
1162 }
1163 py_obj_t *state = m_new(py_obj_t, 1 + o->u_gen_wrap.n_state);
1164 // put function object at first slot in state (to keep u_gen_instance small)
1165 state[0] = o_fun;
1166 // init args
1167 for (int i = 0; i < n_args; i++) {
1168 state[1 + i] = args[n_args - 1 - i];
1169 }
1170 py_obj_base_t *o2 = m_new(py_obj_base_t, 1);
1171 o2->kind = O_GEN_INSTANCE;
1172 o2->u_gen_instance.state = state;
1173 o2->u_gen_instance.ip = o_fun->u_fun_bc.code;
1174 o2->u_gen_instance.sp = state + o->u_gen_wrap.n_state;
1175 return o2;
1176
Damiena3977762013-10-09 23:10:10 +01001177 } else if (IS_O(fun, O_BOUND_METH)) {
1178 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001179 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);
1180 if (n_args == 0) {
1181 return rt_call_function_n(o->u_bound_meth.meth, 1, &o->u_bound_meth.self);
1182 } else if (n_args == 1) {
1183 py_obj_t args2[2];
1184 args2[1] = o->u_bound_meth.self;
1185 args2[0] = args[0];
1186 return rt_call_function_n(o->u_bound_meth.meth, 2, args2);
1187 } else {
1188 // TODO not implemented
1189 assert(0);
1190 return py_const_none;
1191 //return rt_call_function_2(o->u_bound_meth.meth, n_args + 1, o->u_bound_meth.self + args);
1192 }
1193
Damiena3977762013-10-09 23:10:10 +01001194 } else if (IS_O(fun, O_CLASS)) {
1195 // instantiate an instance of a class
Damieneb19efb2013-10-10 22:06:54 +01001196 if (n_args != 0) {
1197 n_args_fun = 0;
1198 goto bad_n_args;
1199 }
Damiena3977762013-10-09 23:10:10 +01001200 DEBUG_OP_printf("instantiate object of class %p with no args\n", fun);
1201 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1202 o->kind = O_OBJ;
1203 o->u_obj.class = fun;
1204 o->u_obj.members = py_map_new(MAP_QSTR, 0);
1205 return o;
Damieneb19efb2013-10-10 22:06:54 +01001206
Damien429d7192013-10-04 19:53:11 +01001207 } else {
Damieneb19efb2013-10-10 22:06:54 +01001208 printf("fun %p %d\n", fun, ((py_obj_base_t*)fun)->kind);
Damien429d7192013-10-04 19:53:11 +01001209 assert(0);
1210 return py_const_none;
1211 }
Damien429d7192013-10-04 19:53:11 +01001212
Damieneb19efb2013-10-10 22:06:54 +01001213bad_n_args:
Damienbd254452013-10-16 20:39:12 +01001214 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 +01001215}
1216
Damiena3977762013-10-09 23:10:10 +01001217// args contains: arg(n_args-1) arg(n_args-2) ... arg(0) self/NULL fun
1218// if n_args==0 then there are only self/NULL and fun
1219py_obj_t rt_call_method_n(int n_args, const py_obj_t *args) {
Damien7f5dacf2013-10-10 11:24:39 +01001220 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 +01001221 return rt_call_function_n(args[n_args + 1], n_args + ((args[n_args] == NULL) ? 0 : 1), args);
1222}
1223
Damien429d7192013-10-04 19:53:11 +01001224// items are in reverse order
Damienc226dca2013-10-16 16:12:52 +01001225py_obj_t rt_build_tuple(int n_args, py_obj_t *items) {
1226 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1227 o->kind = O_TUPLE;
1228 o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args;
1229 o->u_tuple_list.len = n_args;
1230 o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc);
1231 for (int i = 0; i < n_args; i++) {
1232 o->u_tuple_list.items[i] = items[n_args - i - 1];
1233 }
1234 return o;
1235}
1236
1237// items are in reverse order
Damien429d7192013-10-04 19:53:11 +01001238py_obj_t rt_build_list(int n_args, py_obj_t *items) {
1239 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1240 o->kind = O_LIST;
Damienc226dca2013-10-16 16:12:52 +01001241 o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args;
1242 o->u_tuple_list.len = n_args;
1243 o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc);
Damien429d7192013-10-04 19:53:11 +01001244 for (int i = 0; i < n_args; i++) {
Damienc226dca2013-10-16 16:12:52 +01001245 o->u_tuple_list.items[i] = items[n_args - i - 1];
Damien429d7192013-10-04 19:53:11 +01001246 }
1247 return o;
1248}
1249
1250py_obj_t py_set_lookup(py_obj_t o_in, py_obj_t index, bool add_if_not_found) {
1251 assert(IS_O(o_in, O_SET));
1252 py_obj_base_t *o = o_in;
1253 int hash = py_obj_hash(index);
1254 int pos = hash % o->u_set.alloc;
1255 for (;;) {
1256 py_obj_t elem = o->u_set.table[pos];
1257 if (elem == NULL) {
1258 // not in table
1259 if (add_if_not_found) {
1260 if (o->u_set.used + 1 >= o->u_set.alloc) {
1261 // not enough room in table, rehash it
1262 int old_alloc = o->u_set.alloc;
1263 py_obj_t *old_table = o->u_set.table;
1264 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(o->u_set.alloc + 1);
1265 o->u_set.used = 0;
1266 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
1267 for (int i = 0; i < old_alloc; i++) {
1268 if (old_table[i] != NULL) {
1269 py_set_lookup(o, old_table[i], true);
1270 }
1271 }
1272 m_free(old_table);
1273 // restart the search for the new element
1274 pos = hash % o->u_set.alloc;
1275 } else {
1276 o->u_set.used += 1;
1277 o->u_set.table[pos] = index;
1278 return index;
1279 }
1280 } else {
1281 return NULL;
1282 }
1283 } else if (py_obj_equal(elem, index)) {
1284 // found it
1285 return elem;
1286 } else {
1287 // not yet found, keep searching in this table
1288 pos = (pos + 1) % o->u_set.alloc;
1289 }
1290 }
1291}
1292
1293py_obj_t rt_build_set(int n_args, py_obj_t *items) {
1294 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1295 o->kind = O_SET;
1296 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(n_args + 1);
1297 o->u_set.used = 0;
1298 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
1299 for (int i = 0; i < o->u_set.alloc; i++) {
1300 o->u_set.table[i] = NULL;
1301 }
1302 for (int i = 0; i < n_args; i++) {
1303 py_set_lookup(o, items[i], true);
1304 }
1305 return o;
1306}
1307
1308py_obj_t rt_build_map(int n_args) {
1309 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1310 o->kind = O_MAP;
1311 py_map_init(&o->u_map, MAP_PY_OBJ, n_args);
1312 return o;
1313}
1314
1315py_obj_t rt_store_map(py_obj_t map, py_obj_t key, py_obj_t value) {
1316 assert(IS_O(map, O_MAP)); // should always be
1317 py_map_lookup(map, key, true)->value = value;
1318 return map;
1319}
1320
Damiena3977762013-10-09 23:10:10 +01001321py_obj_t build_bound_method(py_obj_t self, py_obj_t meth) {
1322 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1323 o->kind = O_BOUND_METH;
1324 o->u_bound_meth.meth = meth;
1325 o->u_bound_meth.self = self;
1326 return o;
1327}
1328
1329py_obj_t rt_load_attr(py_obj_t base, qstr attr) {
1330 DEBUG_OP_printf("load attr %s\n", qstr_str(attr));
1331 if (IS_O(base, O_LIST) && attr == q_append) {
1332 return build_bound_method(base, fun_list_append);
1333 } else if (IS_O(base, O_CLASS)) {
1334 py_obj_base_t *o = base;
1335 py_map_elem_t *elem = py_qstr_map_lookup(o->u_class.locals, attr, false);
1336 if (elem == NULL) {
1337 goto no_attr;
1338 }
1339 return elem->value;
1340 } else if (IS_O(base, O_OBJ)) {
1341 // logic: look in obj members then class locals (TODO check this against CPython)
1342 py_obj_base_t *o = base;
1343 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false);
1344 if (elem != NULL) {
1345 // object member, always treated as a value
1346 return elem->value;
1347 }
1348 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1349 if (elem != NULL) {
1350 if (py_obj_is_callable(elem->value)) {
1351 // class member is callable so build a bound method
1352 return build_bound_method(base, elem->value);
1353 } else {
1354 // class member is a value, so just return that value
1355 return elem->value;
1356 }
1357 }
1358 goto no_attr;
1359 }
1360
1361no_attr:
Damience89a212013-10-15 22:25:17 +01001362 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 +01001363}
1364
1365void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest) {
1366 DEBUG_OP_printf("load method %s\n", qstr_str(attr));
Damienbd254452013-10-16 20:39:12 +01001367 if (IS_O(base, O_GEN_INSTANCE) && attr == q___next__) {
1368 dest[1] = fun_gen_instance_next;
1369 dest[0] = base;
1370 return;
1371 } else if (IS_O(base, O_LIST) && attr == q_append) {
Damiena3977762013-10-09 23:10:10 +01001372 dest[1] = fun_list_append;
1373 dest[0] = base;
1374 return;
1375 } else if (IS_O(base, O_OBJ)) {
1376 // logic: look in obj members then class locals (TODO check this against CPython)
1377 py_obj_base_t *o = base;
1378 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false);
1379 if (elem != NULL) {
1380 // object member, always treated as a value
1381 dest[1] = elem->value;
1382 dest[0] = NULL;
1383 return;
1384 }
1385 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1386 if (elem != NULL) {
1387 if (py_obj_is_callable(elem->value)) {
1388 // class member is callable so build a bound method
1389 dest[1] = elem->value;
1390 dest[0] = base;
1391 return;
1392 } else {
1393 // class member is a value, so just return that value
1394 dest[1] = elem->value;
1395 dest[0] = NULL;
1396 return;
1397 }
1398 }
1399 goto no_attr;
1400 }
1401
1402no_attr:
1403 dest[1] = rt_load_attr(base, attr);
1404 dest[0] = NULL;
1405}
1406
1407void rt_store_attr(py_obj_t base, qstr attr, py_obj_t val) {
1408 DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), val);
1409 if (IS_O(base, O_OBJ)) {
1410 // logic: look in class locals (no add) then obj members (add) (TODO check this against CPython)
1411 py_obj_base_t *o = base;
1412 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1413 if (elem != NULL) {
1414 elem->value = val;
1415 } else {
1416 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, true)->value = val;
1417 }
1418 } else {
1419 printf("?AttributeError: '%s' object has no attribute '%s'\n", py_obj_get_type_str(base), qstr_str(attr));
1420 assert(0);
1421 }
1422}
1423
Damien429d7192013-10-04 19:53:11 +01001424void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t value) {
Damienc226dca2013-10-16 16:12:52 +01001425 if (IS_O(base, O_LIST)) {
Damien429d7192013-10-04 19:53:11 +01001426 // list store
Damienc226dca2013-10-16 16:12:52 +01001427 uint i = get_index(base, index);
1428 ((py_obj_base_t*)base)->u_tuple_list.items[i] = value;
Damien429d7192013-10-04 19:53:11 +01001429 } else if (IS_O(base, O_MAP)) {
1430 // map store
1431 py_map_lookup(base, index, true)->value = value;
1432 } else {
1433 assert(0);
1434 }
1435}
1436
Damience89a212013-10-15 22:25:17 +01001437py_obj_t rt_getiter(py_obj_t o_in) {
Damienbd254452013-10-16 20:39:12 +01001438 if (IS_O(o_in, O_GEN_INSTANCE)) {
1439 return o_in;
1440 } else if (IS_O(o_in, O_RANGE)) {
Damience89a212013-10-15 22:25:17 +01001441 py_obj_base_t *o = o_in;
1442 return py_obj_new_range_iterator(o->u_range.start, o->u_range.stop, o->u_range.step);
Damienc226dca2013-10-16 16:12:52 +01001443 } else if (IS_O(o_in, O_TUPLE)) {
1444 return py_obj_new_tuple_iterator(o_in, 0);
1445 } else if (IS_O(o_in, O_LIST)) {
1446 return py_obj_new_list_iterator(o_in, 0);
Damience89a212013-10-15 22:25:17 +01001447 } else {
1448 nlr_jump(py_obj_new_exception_2(q_TypeError, "'%s' object is not iterable", py_obj_get_type_str(o_in), NULL));
1449 }
1450}
1451
1452py_obj_t rt_iternext(py_obj_t o_in) {
Damienbd254452013-10-16 20:39:12 +01001453 if (IS_O(o_in, O_GEN_INSTANCE)) {
1454 py_obj_base_t *self = o_in;
1455 py_obj_base_t *fun = self->u_gen_instance.state[0];
1456 assert(fun->kind == O_FUN_BC);
1457 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);
1458 if (yield) {
1459 return *self->u_gen_instance.sp;
1460 } else {
1461 if (*self->u_gen_instance.sp == py_const_none) {
1462 return py_const_stop_iteration;
1463 } else {
1464 // TODO return StopIteration with value *self->u_gen_instance.sp
1465 return py_const_stop_iteration;
1466 }
1467 }
1468
1469 } else if (IS_O(o_in, O_RANGE_IT)) {
Damience89a212013-10-15 22:25:17 +01001470 py_obj_base_t *o = o_in;
1471 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)) {
1472 py_obj_t o_out = TO_SMALL_INT(o->u_range_it.cur);
1473 o->u_range_it.cur += o->u_range_it.step;
1474 return o_out;
1475 } else {
1476 return py_const_stop_iteration;
1477 }
Damienbd254452013-10-16 20:39:12 +01001478
Damienc226dca2013-10-16 16:12:52 +01001479 } else if (IS_O(o_in, O_TUPLE_IT) || IS_O(o_in, O_LIST_IT)) {
1480 py_obj_base_t *o = o_in;
1481 if (o->u_tuple_list_it.cur < o->u_tuple_list_it.obj->u_tuple_list.len) {
1482 py_obj_t o_out = o->u_tuple_list_it.obj->u_tuple_list.items[o->u_tuple_list_it.cur];
1483 o->u_tuple_list_it.cur += 1;
1484 return o_out;
1485 } else {
1486 return py_const_stop_iteration;
1487 }
Damienbd254452013-10-16 20:39:12 +01001488
Damience89a212013-10-15 22:25:17 +01001489 } else {
1490 nlr_jump(py_obj_new_exception_2(q_TypeError, "? '%s' object is not iterable", py_obj_get_type_str(o_in), NULL));
1491 }
1492}
1493
Damien429d7192013-10-04 19:53:11 +01001494void *rt_fun_table[RT_F_NUMBER_OF] = {
1495 rt_load_const_str,
1496 rt_load_name,
1497 rt_load_global,
Damien7f5dacf2013-10-10 11:24:39 +01001498 rt_load_build_class,
Damien429d7192013-10-04 19:53:11 +01001499 rt_load_attr,
1500 rt_load_method,
1501 rt_store_name,
Damien7f5dacf2013-10-10 11:24:39 +01001502 rt_store_attr,
Damien429d7192013-10-04 19:53:11 +01001503 rt_store_subscr,
1504 rt_is_true,
1505 rt_unary_op,
1506 rt_build_list,
1507 rt_build_map,
1508 rt_store_map,
1509 rt_build_set,
1510 rt_make_function_from_id,
Damieneb19efb2013-10-10 22:06:54 +01001511 rt_call_function_n,
Damien7f5dacf2013-10-10 11:24:39 +01001512 rt_call_method_n,
Damien429d7192013-10-04 19:53:11 +01001513 rt_binary_op,
1514 rt_compare_op,
1515};
1516
1517/*
1518void rt_f_vector(rt_fun_kind_t fun_kind) {
1519 (rt_f_table[fun_kind])();
1520}
1521*/