blob: d367530ccc0fa29c1f3ff4fa15419756309ec7a4 [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;
Damien5ac1b2e2013-10-18 19:58:12 +0100195 map->table = m_new0(py_map_elem_t, map->alloc);
Damien429d7192013-10-04 19:53:11 +0100196}
197
198py_map_t *py_map_new(py_map_kind_t kind, int n) {
199 py_map_t *map = m_new(py_map_t, 1);
200 py_map_init(map, kind, n);
201 return map;
202}
203
Damien5ac1b2e2013-10-18 19:58:12 +0100204machine_int_t py_obj_hash(py_obj_t o_in) {
205 if (o_in == py_const_false) {
206 return 0; // needs to hash to same as the integer 0, since False==0
207 } else if (o_in == py_const_true) {
208 return 1; // needs to hash to same as the integer 1, since True==1
209 } else if (IS_SMALL_INT(o_in)) {
Damien429d7192013-10-04 19:53:11 +0100210 return FROM_SMALL_INT(o_in);
Damien5ac1b2e2013-10-18 19:58:12 +0100211 } else if (IS_O(o_in, O_CONST)) {
212 return (machine_int_t)o_in;
Damien429d7192013-10-04 19:53:11 +0100213 } else if (IS_O(o_in, O_STR)) {
214 return ((py_obj_base_t*)o_in)->u_str;
215 } else {
216 assert(0);
217 return 0;
218 }
219}
220
Damien5ac1b2e2013-10-18 19:58:12 +0100221// this function implements the '==' operator (and so the inverse of '!=')
222// from the python language reference:
223// "The objects need not have the same type. If both are numbers, they are converted
224// to a common type. Otherwise, the == and != operators always consider objects of
225// different types to be unequal."
226// note also that False==0 and True==1 are true expressions
Damien429d7192013-10-04 19:53:11 +0100227bool py_obj_equal(py_obj_t o1, py_obj_t o2) {
228 if (o1 == o2) {
229 return true;
Damien5ac1b2e2013-10-18 19:58:12 +0100230 } else if (IS_SMALL_INT(o1) || IS_SMALL_INT(o2)) {
231 if (IS_SMALL_INT(o1) && IS_SMALL_INT(o2)) {
232 return false;
233 } else {
234 if (IS_SMALL_INT(o2)) {
235 py_obj_t temp = o1; o1 = o2; o2 = temp;
236 }
237 // o1 is the SMALL_INT, o2 is not
238 py_small_int_t val = FROM_SMALL_INT(o1);
239 if (o2 == py_const_false) {
240 return val == 0;
241 } else if (o2 == py_const_true) {
242 return val == 1;
243 } else {
244 return false;
245 }
246 }
Damien429d7192013-10-04 19:53:11 +0100247 } else if (IS_O(o1, O_STR) && IS_O(o2, O_STR)) {
248 return ((py_obj_base_t*)o1)->u_str == ((py_obj_base_t*)o2)->u_str;
249 } else {
250 assert(0);
251 return false;
252 }
253}
254
255py_map_elem_t* py_map_lookup_helper(py_map_t *map, py_obj_t index, bool add_if_not_found) {
256 bool is_map_py_obj = (map->kind == MAP_PY_OBJ);
257 machine_uint_t hash;
258 if (is_map_py_obj) {
259 hash = py_obj_hash(index);
260 } else {
261 hash = (machine_uint_t)index;
262 }
263 uint pos = hash % map->alloc;
264 for (;;) {
265 py_map_elem_t *elem = &map->table[pos];
266 if (elem->key == NULL) {
267 // not in table
268 if (add_if_not_found) {
269 if (map->used + 1 >= map->alloc) {
270 // not enough room in table, rehash it
271 int old_alloc = map->alloc;
272 py_map_elem_t *old_table = map->table;
273 map->alloc = get_doubling_prime_greater_or_equal_to(map->alloc + 1);
274 map->used = 0;
Damien5ac1b2e2013-10-18 19:58:12 +0100275 map->table = m_new0(py_map_elem_t, map->alloc);
Damien429d7192013-10-04 19:53:11 +0100276 for (int i = 0; i < old_alloc; i++) {
277 if (old_table[i].key != NULL) {
278 py_map_lookup_helper(map, old_table[i].key, true)->value = old_table[i].value;
279 }
280 }
281 m_free(old_table);
282 // restart the search for the new element
283 pos = hash % map->alloc;
284 } else {
285 map->used += 1;
286 elem->key = index;
287 return elem;
288 }
289 } else {
290 return NULL;
291 }
292 } else if (elem->key == index || (is_map_py_obj && py_obj_equal(elem->key, index))) {
293 // found it
Damien5ac1b2e2013-10-18 19:58:12 +0100294 /* it seems CPython does not replace the index; try x={True:'true'};x[1]='one';x
Damien429d7192013-10-04 19:53:11 +0100295 if (add_if_not_found) {
296 elem->key = index;
297 }
Damien5ac1b2e2013-10-18 19:58:12 +0100298 */
Damien429d7192013-10-04 19:53:11 +0100299 return elem;
300 } else {
301 // not yet found, keep searching in this table
302 pos = (pos + 1) % map->alloc;
303 }
304 }
305}
306
307py_map_elem_t* py_qstr_map_lookup(py_map_t *map, qstr index, bool add_if_not_found) {
308 py_obj_t o = (py_obj_t)(machine_uint_t)index;
309 return py_map_lookup_helper(map, o, add_if_not_found);
310}
311
312py_map_elem_t* py_map_lookup(py_obj_t o, py_obj_t index, bool add_if_not_found) {
313 assert(IS_O(o, O_MAP));
314 return py_map_lookup_helper(&((py_obj_base_t *)o)->u_map, index, add_if_not_found);
315}
316
317static bool fit_small_int(py_small_int_t o) {
318 return true;
319}
320
321py_obj_t py_obj_new_const(const char *id) {
322 py_obj_base_t *o = m_new(py_obj_base_t, 1);
323 o->kind = O_CONST;
324 o->id = id;
325 return (py_obj_t)o;
326}
327
328py_obj_t py_obj_new_str(qstr qstr) {
329 py_obj_base_t *o = m_new(py_obj_base_t, 1);
330 o->kind = O_STR;
331 o->u_str = qstr;
332 return (py_obj_t)o;
333}
334
Damien3ef4abb2013-10-12 16:53:13 +0100335#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100336py_obj_t py_obj_new_float(float_t val) {
337 py_obj_base_t *o = m_new(py_obj_base_t, 1);
338 o->kind = O_FLOAT;
Damiene4af64f2013-10-06 12:04:13 +0100339 o->u_flt = val;
Damien429d7192013-10-04 19:53:11 +0100340 return (py_obj_t)o;
341}
342#endif
343
Damience89a212013-10-15 22:25:17 +0100344py_obj_t py_obj_new_exception_0(qstr id) {
345 py_obj_base_t *o = m_new(py_obj_base_t, 1);
346 o->kind = O_EXCEPTION_0;
347 o->u_exc0.id = id;
348 return (py_obj_t)o;
349}
350
351py_obj_t py_obj_new_exception_2(qstr id, const char *fmt, const char *s1, const char *s2) {
352 py_obj_base_t *o = m_new(py_obj_base_t, 1);
353 o->kind = O_EXCEPTION_2;
354 o->u_exc2.id = id;
355 o->u_exc2.fmt = fmt;
356 o->u_exc2.s1 = s1;
357 o->u_exc2.s2 = s2;
358 return (py_obj_t)o;
359}
360
361// range is a class and instances are immutable sequence objects
362py_obj_t py_obj_new_range(int start, int stop, int step) {
363 py_obj_base_t *o = m_new(py_obj_base_t, 1);
364 o->kind = O_RANGE;
365 o->u_range.start = start;
366 o->u_range.stop = stop;
367 o->u_range.step = step;
368 return o;
369}
370
371py_obj_t py_obj_new_range_iterator(int cur, int stop, int step) {
372 py_obj_base_t *o = m_new(py_obj_base_t, 1);
373 o->kind = O_RANGE_IT;
374 o->u_range_it.cur = cur;
375 o->u_range_it.stop = stop;
376 o->u_range_it.step = step;
377 return o;
378}
379
Damienc226dca2013-10-16 16:12:52 +0100380py_obj_t py_obj_new_tuple_iterator(py_obj_base_t *tuple, int cur) {
381 py_obj_base_t *o = m_new(py_obj_base_t, 1);
382 o->kind = O_TUPLE_IT;
383 o->u_tuple_list_it.obj = tuple;
384 o->u_tuple_list_it.cur = cur;
385 return o;
386}
387
388py_obj_t py_obj_new_list_iterator(py_obj_base_t *list, int cur) {
389 py_obj_base_t *o = m_new(py_obj_base_t, 1);
390 o->kind = O_LIST_IT;
391 o->u_tuple_list_it.obj = list;
392 o->u_tuple_list_it.cur = cur;
393 return o;
394}
395
396py_obj_t rt_list_append(py_obj_t self_in, py_obj_t arg) {
Damien429d7192013-10-04 19:53:11 +0100397 assert(IS_O(self_in, O_LIST));
398 py_obj_base_t *self = self_in;
Damienc226dca2013-10-16 16:12:52 +0100399 if (self->u_tuple_list.len >= self->u_tuple_list.alloc) {
400 self->u_tuple_list.alloc *= 2;
401 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 +0100402 }
Damienc226dca2013-10-16 16:12:52 +0100403 self->u_tuple_list.items[self->u_tuple_list.len++] = arg;
Damien429d7192013-10-04 19:53:11 +0100404 return arg;
405}
406
Damienbd254452013-10-16 20:39:12 +0100407py_obj_t rt_gen_instance_next(py_obj_t self_in) {
408 py_obj_t ret = rt_iternext(self_in);
409 if (ret == py_const_stop_iteration) {
410 nlr_jump(py_obj_new_exception_0(qstr_from_str_static("StopIteration")));
411 } else {
412 return ret;
413 }
414}
415
Damien429d7192013-10-04 19:53:11 +0100416static qstr q_append;
417static qstr q_print;
418static qstr q_len;
419static qstr q___build_class__;
Damienbd254452013-10-16 20:39:12 +0100420static qstr q___next__;
Damience89a212013-10-15 22:25:17 +0100421static qstr q_AttributeError;
Damienc226dca2013-10-16 16:12:52 +0100422static qstr q_IndexError;
Damien5ac1b2e2013-10-18 19:58:12 +0100423static qstr q_KeyError;
Damience89a212013-10-15 22:25:17 +0100424static qstr q_NameError;
425static qstr q_TypeError;
Damien429d7192013-10-04 19:53:11 +0100426
427typedef enum {
Damien826005c2013-10-05 23:17:28 +0100428 PY_CODE_NONE,
Damien429d7192013-10-04 19:53:11 +0100429 PY_CODE_BYTE,
Damien826005c2013-10-05 23:17:28 +0100430 PY_CODE_NATIVE,
431 PY_CODE_INLINE_ASM,
Damien429d7192013-10-04 19:53:11 +0100432} py_code_kind_t;
433
434typedef struct _py_code_t {
435 py_code_kind_t kind;
436 int n_args;
Damienbd254452013-10-16 20:39:12 +0100437 int n_locals;
438 int n_stack;
439 bool is_generator;
Damien429d7192013-10-04 19:53:11 +0100440 union {
441 struct {
Damien429d7192013-10-04 19:53:11 +0100442 byte *code;
443 uint len;
444 } u_byte;
Damien826005c2013-10-05 23:17:28 +0100445 struct {
446 py_fun_t fun;
447 } u_native;
448 struct {
Damiene4af64f2013-10-06 12:04:13 +0100449 void *fun;
Damien826005c2013-10-05 23:17:28 +0100450 } u_inline_asm;
Damien429d7192013-10-04 19:53:11 +0100451 };
452} py_code_t;
453
454static int next_unique_code_id;
455static py_code_t *unique_codes;
456
457py_obj_t fun_list_append;
Damienbd254452013-10-16 20:39:12 +0100458py_obj_t fun_gen_instance_next;
Damien429d7192013-10-04 19:53:11 +0100459
Damien5ac1b2e2013-10-18 19:58:12 +0100460py_obj_t py_builtin___repl_print__(py_obj_t o) {
461 if (o != py_const_none) {
462 py_obj_print(o);
463 printf("\n");
464 }
465 return py_const_none;
466}
467
Damien429d7192013-10-04 19:53:11 +0100468py_obj_t py_builtin_print(py_obj_t o) {
469 if (IS_O(o, O_STR)) {
470 // special case, print string raw
471 printf("%s\n", qstr_str(((py_obj_base_t*)o)->u_str));
472 } else {
473 // print the object Python style
474 py_obj_print(o);
475 printf("\n");
476 }
477 return py_const_none;
478}
479
480py_obj_t py_builtin_len(py_obj_t o_in) {
481 py_small_int_t len = 0;
Damienc226dca2013-10-16 16:12:52 +0100482 if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) {
Damien429d7192013-10-04 19:53:11 +0100483 py_obj_base_t *o = o_in;
Damienc226dca2013-10-16 16:12:52 +0100484 len = o->u_tuple_list.len;
Damien429d7192013-10-04 19:53:11 +0100485 } else if (IS_O(o_in, O_MAP)) {
486 py_obj_base_t *o = o_in;
487 len = o->u_map.used;
488 } else {
489 assert(0);
490 }
491 return TO_SMALL_INT(len);
492}
493
Damiena3977762013-10-09 23:10:10 +0100494py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name) {
495 // we differ from CPython: we set the new __locals__ object here
Damieneb19efb2013-10-10 22:06:54 +0100496 py_map_t *old_locals = map_locals;
Damiena3977762013-10-09 23:10:10 +0100497 py_map_t *class_locals = py_map_new(MAP_QSTR, 0);
Damieneb19efb2013-10-10 22:06:54 +0100498 map_locals = class_locals;
Damiena3977762013-10-09 23:10:10 +0100499
500 // call the class code
501 rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef);
502
503 // restore old __locals__ object
504 map_locals = old_locals;
505
506 // create and return the new class
Damien429d7192013-10-04 19:53:11 +0100507 py_obj_base_t *o = m_new(py_obj_base_t, 1);
508 o->kind = O_CLASS;
Damiena3977762013-10-09 23:10:10 +0100509 o->u_class.locals = class_locals;
Damien429d7192013-10-04 19:53:11 +0100510 return o;
511}
512
Damience89a212013-10-15 22:25:17 +0100513py_obj_t py_builtin_range(py_obj_t o_arg) {
514 return py_obj_new_range(0, rt_get_int(o_arg), 1);
515}
516
Damiena1ddfcc2013-10-10 23:25:50 +0100517#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100518FILE *fp_native = NULL;
Damiena1ddfcc2013-10-10 23:25:50 +0100519#endif
Damien429d7192013-10-04 19:53:11 +0100520
521void rt_init() {
522 q_append = qstr_from_str_static("append");
523 q_print = qstr_from_str_static("print");
524 q_len = qstr_from_str_static("len");
525 q___build_class__ = qstr_from_str_static("__build_class__");
Damienbd254452013-10-16 20:39:12 +0100526 q___next__ = qstr_from_str_static("__next__");
Damience89a212013-10-15 22:25:17 +0100527 q_AttributeError = qstr_from_str_static("AttributeError");
Damienc226dca2013-10-16 16:12:52 +0100528 q_IndexError = qstr_from_str_static("IndexError");
Damien5ac1b2e2013-10-18 19:58:12 +0100529 q_KeyError = qstr_from_str_static("KeyError");
Damience89a212013-10-15 22:25:17 +0100530 q_NameError = qstr_from_str_static("NameError");
531 q_TypeError = qstr_from_str_static("TypeError");
Damien429d7192013-10-04 19:53:11 +0100532
533 py_const_none = py_obj_new_const("None");
534 py_const_false = py_obj_new_const("False");
535 py_const_true = py_obj_new_const("True");
Damience89a212013-10-15 22:25:17 +0100536 py_const_stop_iteration = py_obj_new_const("StopIteration");
Damien429d7192013-10-04 19:53:11 +0100537
Damieneb19efb2013-10-10 22:06:54 +0100538 // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
539 map_locals = map_globals = py_map_new(MAP_QSTR, 1);
540 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 +0100541
542 py_map_init(&map_builtins, MAP_QSTR, 3);
Damien5ac1b2e2013-10-18 19:58:12 +0100543 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 +0100544 py_qstr_map_lookup(&map_builtins, q_print, true)->value = rt_make_function_1(py_builtin_print);
545 py_qstr_map_lookup(&map_builtins, q_len, true)->value = rt_make_function_1(py_builtin_len);
546 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 +0100547 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 +0100548
Damien5ac1b2e2013-10-18 19:58:12 +0100549 next_unique_code_id = 2; // 1 is reserved for the __main__ module scope
Damien429d7192013-10-04 19:53:11 +0100550 unique_codes = NULL;
551
Damienc226dca2013-10-16 16:12:52 +0100552 fun_list_append = rt_make_function_2(rt_list_append);
Damienbd254452013-10-16 20:39:12 +0100553 fun_gen_instance_next = rt_make_function_1(rt_gen_instance_next);
Damien429d7192013-10-04 19:53:11 +0100554
Damiena1ddfcc2013-10-10 23:25:50 +0100555#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100556 fp_native = fopen("out-native", "wb");
Damiena1ddfcc2013-10-10 23:25:50 +0100557#endif
Damien429d7192013-10-04 19:53:11 +0100558}
559
560void rt_deinit() {
Damiena1ddfcc2013-10-10 23:25:50 +0100561#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100562 if (fp_native != NULL) {
563 fclose(fp_native);
564 }
Damiena1ddfcc2013-10-10 23:25:50 +0100565#endif
Damien429d7192013-10-04 19:53:11 +0100566}
567
Damien5ac1b2e2013-10-18 19:58:12 +0100568int rt_get_unique_code_id(bool is_main_module) {
569 if (is_main_module) {
570 return 1;
571 } else {
572 return next_unique_code_id++;
573 }
Damien429d7192013-10-04 19:53:11 +0100574}
575
Damien826005c2013-10-05 23:17:28 +0100576static void alloc_unique_codes() {
Damien429d7192013-10-04 19:53:11 +0100577 if (unique_codes == NULL) {
578 unique_codes = m_new(py_code_t, next_unique_code_id);
Damien826005c2013-10-05 23:17:28 +0100579 for (int i = 0; i < next_unique_code_id; i++) {
580 unique_codes[i].kind = PY_CODE_NONE;
581 }
Damien429d7192013-10-04 19:53:11 +0100582 }
Damien826005c2013-10-05 23:17:28 +0100583}
584
Damienbd254452013-10-16 20:39:12 +0100585void 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 +0100586 alloc_unique_codes();
587
588 assert(unique_code_id < next_unique_code_id);
589 unique_codes[unique_code_id].kind = PY_CODE_BYTE;
590 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +0100591 unique_codes[unique_code_id].n_locals = n_locals;
592 unique_codes[unique_code_id].n_stack = n_stack;
593 unique_codes[unique_code_id].is_generator = is_generator;
Damien826005c2013-10-05 23:17:28 +0100594 unique_codes[unique_code_id].u_byte.code = code;
595 unique_codes[unique_code_id].u_byte.len = len;
596
597 DEBUG_printf("assign byte code: id=%d code=%p len=%u n_args=%d\n", unique_code_id, code, len, n_args);
598}
599
600void rt_assign_native_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
601 alloc_unique_codes();
602
Damienb05d7072013-10-05 13:37:10 +0100603 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
Damien429d7192013-10-04 19:53:11 +0100604 unique_codes[unique_code_id].kind = PY_CODE_NATIVE;
605 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +0100606 unique_codes[unique_code_id].n_locals = 0;
607 unique_codes[unique_code_id].n_stack = 0;
608 unique_codes[unique_code_id].is_generator = false;
Damien429d7192013-10-04 19:53:11 +0100609 unique_codes[unique_code_id].u_native.fun = fun;
610
Damiena1ddfcc2013-10-10 23:25:50 +0100611#ifdef DEBUG_PRINT
Damien429d7192013-10-04 19:53:11 +0100612 DEBUG_printf("assign native code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
613 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
614 for (int i = 0; i < 128 && i < len; i++) {
615 if (i > 0 && i % 16 == 0) {
616 DEBUG_printf("\n");
617 }
618 DEBUG_printf(" %02x", fun_data[i]);
619 }
620 DEBUG_printf("\n");
621
Damiena1ddfcc2013-10-10 23:25:50 +0100622#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100623 if (fp_native != NULL) {
624 fwrite(fun_data, len, 1, fp_native);
Damien13ed3a62013-10-08 09:05:10 +0100625 fflush(fp_native);
Damien429d7192013-10-04 19:53:11 +0100626 }
Damiena1ddfcc2013-10-10 23:25:50 +0100627#endif
628#endif
Damien429d7192013-10-04 19:53:11 +0100629}
630
Damien826005c2013-10-05 23:17:28 +0100631void rt_assign_inline_asm_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
632 alloc_unique_codes();
Damien429d7192013-10-04 19:53:11 +0100633
Damien826005c2013-10-05 23:17:28 +0100634 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
635 unique_codes[unique_code_id].kind = PY_CODE_INLINE_ASM;
636 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +0100637 unique_codes[unique_code_id].n_locals = 0;
638 unique_codes[unique_code_id].n_stack = 0;
639 unique_codes[unique_code_id].is_generator = false;
Damien826005c2013-10-05 23:17:28 +0100640 unique_codes[unique_code_id].u_inline_asm.fun = fun;
641
Damiena1ddfcc2013-10-10 23:25:50 +0100642#ifdef DEBUG_PRINT
Damien826005c2013-10-05 23:17:28 +0100643 DEBUG_printf("assign inline asm code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
644 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
645 for (int i = 0; i < 128 && i < len; i++) {
646 if (i > 0 && i % 16 == 0) {
647 DEBUG_printf("\n");
648 }
649 DEBUG_printf(" %02x", fun_data[i]);
650 }
651 DEBUG_printf("\n");
652
Damiena1ddfcc2013-10-10 23:25:50 +0100653#ifdef WRITE_NATIVE
Damien826005c2013-10-05 23:17:28 +0100654 if (fp_native != NULL) {
655 fwrite(fun_data, len, 1, fp_native);
656 }
Damiena1ddfcc2013-10-10 23:25:50 +0100657#endif
658#endif
Damien429d7192013-10-04 19:53:11 +0100659}
660
Damiena3977762013-10-09 23:10:10 +0100661bool py_obj_is_callable(py_obj_t o_in) {
662 if (IS_SMALL_INT(o_in)) {
663 return false;
664 } else {
665 py_obj_base_t *o = o_in;
666 switch (o->kind) {
667 case O_FUN_0:
668 case O_FUN_1:
669 case O_FUN_2:
670 case O_FUN_N:
671 case O_FUN_BC:
672 case O_FUN_ASM:
Damieneb19efb2013-10-10 22:06:54 +0100673 // what about O_CLASS, and an O_OBJ that has a __call__ method?
Damiena3977762013-10-09 23:10:10 +0100674 return true;
675 default:
676 return false;
677 }
678 }
679}
680
Damien429d7192013-10-04 19:53:11 +0100681const char *py_obj_get_type_str(py_obj_t o_in) {
682 if (IS_SMALL_INT(o_in)) {
683 return "int";
684 } else {
685 py_obj_base_t *o = o_in;
686 switch (o->kind) {
687 case O_CONST:
688 if (o == py_const_none) {
689 return "NoneType";
690 } else {
691 return "bool";
692 }
693 case O_STR:
694 return "str";
Damien3ef4abb2013-10-12 16:53:13 +0100695#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100696 case O_FLOAT:
697 return "float";
698#endif
Damien6cdd3af2013-10-05 18:08:26 +0100699 case O_FUN_0:
700 case O_FUN_1:
701 case O_FUN_2:
702 case O_FUN_N:
703 case O_FUN_BC:
704 return "function";
Damienbd254452013-10-16 20:39:12 +0100705 case O_GEN_INSTANCE:
706 return "generator";
Damienc226dca2013-10-16 16:12:52 +0100707 case O_TUPLE:
708 return "tuple";
Damien429d7192013-10-04 19:53:11 +0100709 case O_LIST:
710 return "list";
Damienc226dca2013-10-16 16:12:52 +0100711 case O_TUPLE_IT:
712 return "tuple_iterator";
713 case O_LIST_IT:
714 return "list_iterator";
Damien429d7192013-10-04 19:53:11 +0100715 case O_SET:
716 return "set";
717 case O_MAP:
718 return "dict";
Damiena3977762013-10-09 23:10:10 +0100719 case O_OBJ:
720 {
721 py_map_elem_t *qn = py_qstr_map_lookup(o->u_obj.class->u_class.locals, qstr_from_str_static("__qualname__"), false);
722 assert(qn != NULL);
723 assert(IS_O(qn->value, O_STR));
724 return qstr_str(((py_obj_base_t*)qn->value)->u_str);
725 }
Damien429d7192013-10-04 19:53:11 +0100726 default:
727 assert(0);
728 return "UnknownType";
729 }
730 }
731}
732
733void py_obj_print(py_obj_t o_in) {
734 if (IS_SMALL_INT(o_in)) {
735 printf("%d", (int)FROM_SMALL_INT(o_in));
736 } else {
737 py_obj_base_t *o = o_in;
738 switch (o->kind) {
739 case O_CONST:
740 printf("%s", o->id);
741 break;
742 case O_STR:
743 // TODO need to escape chars etc
744 printf("'%s'", qstr_str(o->u_str));
745 break;
Damien3ef4abb2013-10-12 16:53:13 +0100746#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100747 case O_FLOAT:
Damiene4af64f2013-10-06 12:04:13 +0100748 printf("%f", o->u_flt);
Damien429d7192013-10-04 19:53:11 +0100749 break;
750#endif
Damienbd254452013-10-16 20:39:12 +0100751 case O_EXCEPTION_0:
752 printf("%s", qstr_str(o->u_exc0.id));
753 break;
Damience89a212013-10-15 22:25:17 +0100754 case O_EXCEPTION_2:
755 printf("%s: ", qstr_str(o->u_exc2.id));
756 printf(o->u_exc2.fmt, o->u_exc2.s1, o->u_exc2.s2);
757 break;
Damienbd254452013-10-16 20:39:12 +0100758 case O_GEN_INSTANCE:
759 printf("<generator object 'fun-name' at %p>", o);
760 break;
Damienc226dca2013-10-16 16:12:52 +0100761 case O_TUPLE:
762 printf("(");
763 for (int i = 0; i < o->u_tuple_list.len; i++) {
Damien429d7192013-10-04 19:53:11 +0100764 if (i > 0) {
765 printf(", ");
766 }
Damienc226dca2013-10-16 16:12:52 +0100767 py_obj_print(o->u_tuple_list.items[i]);
768 }
769 if (o->u_tuple_list.len == 1) {
770 printf(",");
771 }
772 printf(")");
773 break;
774 case O_LIST:
775 printf("[");
776 for (int i = 0; i < o->u_tuple_list.len; i++) {
777 if (i > 0) {
778 printf(", ");
779 }
780 py_obj_print(o->u_tuple_list.items[i]);
Damien429d7192013-10-04 19:53:11 +0100781 }
782 printf("]");
783 break;
784 case O_SET:
785 {
786 bool first = true;
787 printf("{");
788 for (int i = 0; i < o->u_set.alloc; i++) {
789 if (o->u_set.table[i] != NULL) {
790 if (!first) {
791 printf(", ");
792 }
793 first = false;
794 py_obj_print(o->u_set.table[i]);
795 }
796 }
797 printf("}");
798 break;
799 }
800 case O_MAP:
801 {
802 bool first = true;
803 printf("{");
804 for (int i = 0; i < o->u_map.alloc; i++) {
805 if (o->u_map.table[i].key != NULL) {
806 if (!first) {
807 printf(", ");
808 }
809 first = false;
810 py_obj_print(o->u_map.table[i].key);
811 printf(": ");
812 py_obj_print(o->u_map.table[i].value);
813 }
814 }
815 printf("}");
816 break;
817 }
818 default:
Damiena3977762013-10-09 23:10:10 +0100819 printf("<? %d>", o->kind);
Damien429d7192013-10-04 19:53:11 +0100820 assert(0);
821 }
822 }
823}
824
825int rt_is_true(py_obj_t arg) {
826 DEBUG_OP_printf("is true %p\n", arg);
827 if (IS_SMALL_INT(arg)) {
828 if (FROM_SMALL_INT(arg) == 0) {
829 return 0;
830 } else {
831 return 1;
832 }
833 } else if (arg == py_const_none) {
834 return 0;
835 } else if (arg == py_const_false) {
836 return 0;
837 } else if (arg == py_const_true) {
838 return 1;
839 } else {
840 assert(0);
841 return 0;
842 }
843}
844
845int rt_get_int(py_obj_t arg) {
Damienc226dca2013-10-16 16:12:52 +0100846 if (arg == py_const_false) {
847 return 0;
848 } else if (arg == py_const_true) {
849 return 1;
850 } else if (IS_SMALL_INT(arg)) {
Damien429d7192013-10-04 19:53:11 +0100851 return FROM_SMALL_INT(arg);
852 } else {
853 assert(0);
854 return 0;
855 }
856}
857
858py_obj_t rt_load_const_str(qstr qstr) {
859 DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
860 return py_obj_new_str(qstr);
861}
862
863py_obj_t rt_load_name(qstr qstr) {
864 // logic: search locals, globals, builtins
Damiena3977762013-10-09 23:10:10 +0100865 DEBUG_OP_printf("load name %s\n", qstr_str(qstr));
Damieneb19efb2013-10-10 22:06:54 +0100866 py_map_elem_t *elem = py_qstr_map_lookup(map_locals, qstr, false);
Damiena3977762013-10-09 23:10:10 +0100867 if (elem == NULL) {
Damieneb19efb2013-10-10 22:06:54 +0100868 elem = py_qstr_map_lookup(map_globals, qstr, false);
Damiena3977762013-10-09 23:10:10 +0100869 if (elem == NULL) {
870 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
871 if (elem == NULL) {
Damience89a212013-10-15 22:25:17 +0100872 nlr_jump(py_obj_new_exception_2(q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL));
Damiena3977762013-10-09 23:10:10 +0100873 }
874 }
875 }
876 return elem->value;
877}
878
879py_obj_t rt_load_global(qstr qstr) {
880 // logic: search globals, builtins
881 DEBUG_OP_printf("load global %s\n", qstr_str(qstr));
Damieneb19efb2013-10-10 22:06:54 +0100882 py_map_elem_t *elem = py_qstr_map_lookup(map_globals, qstr, false);
Damien429d7192013-10-04 19:53:11 +0100883 if (elem == NULL) {
884 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
885 if (elem == NULL) {
Damience89a212013-10-15 22:25:17 +0100886 nlr_jump(py_obj_new_exception_2(q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL));
Damien429d7192013-10-04 19:53:11 +0100887 }
888 }
889 return elem->value;
890}
891
Damien429d7192013-10-04 19:53:11 +0100892py_obj_t rt_load_build_class() {
893 DEBUG_OP_printf("load_build_class\n");
894 py_map_elem_t *elem = py_qstr_map_lookup(&map_builtins, q___build_class__, false);
895 if (elem == NULL) {
896 printf("name doesn't exist: __build_class__\n");
897 assert(0);
898 }
899 return elem->value;
900}
901
902void rt_store_name(qstr qstr, py_obj_t obj) {
Damiena3977762013-10-09 23:10:10 +0100903 DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qstr), obj);
Damieneb19efb2013-10-10 22:06:54 +0100904 py_qstr_map_lookup(map_locals, qstr, true)->value = obj;
Damiena3977762013-10-09 23:10:10 +0100905}
906
907void rt_store_global(qstr qstr, py_obj_t obj) {
908 DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qstr), obj);
Damieneb19efb2013-10-10 22:06:54 +0100909 py_qstr_map_lookup(map_globals, qstr, true)->value = obj;
Damien429d7192013-10-04 19:53:11 +0100910}
911
912py_obj_t rt_unary_op(int op, py_obj_t arg) {
913 assert(0);
914 return py_const_none;
915}
916
Damienc226dca2013-10-16 16:12:52 +0100917uint get_index(py_obj_base_t *base, py_obj_t index) {
918 // assumes base is O_TUPLE or O_LIST
919 // TODO False and True are considered 0 and 1 for indexing purposes
920 int len = base->u_tuple_list.len;
921 if (IS_SMALL_INT(index)) {
922 int i = FROM_SMALL_INT(index);
923 if (i < 0) {
924 i += len;
925 }
926 if (i < 0 || i >= len) {
927 nlr_jump(py_obj_new_exception_2(q_IndexError, "%s index out of range", py_obj_get_type_str(base), NULL));
928 }
929 return i;
930 } else {
931 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)));
932 }
933}
934
Damien429d7192013-10-04 19:53:11 +0100935py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs) {
936 DEBUG_OP_printf("binary %d %p %p\n", op, lhs, rhs);
937 if (op == RT_BINARY_OP_SUBSCR) {
Damienc226dca2013-10-16 16:12:52 +0100938 if ((IS_O(lhs, O_TUPLE) || IS_O(lhs, O_LIST))) {
Damien5ac1b2e2013-10-18 19:58:12 +0100939 // tuple/list load
Damienc226dca2013-10-16 16:12:52 +0100940 uint index = get_index(lhs, rhs);
941 return ((py_obj_base_t*)lhs)->u_tuple_list.items[index];
Damien5ac1b2e2013-10-18 19:58:12 +0100942 } else if (IS_O(lhs, O_MAP)) {
943 // map load
944 py_map_elem_t *elem = py_map_lookup(lhs, rhs, false);
945 if (elem == NULL) {
946 nlr_jump(py_obj_new_exception_2(q_KeyError, "<value>", NULL, NULL));
947 } else {
948 return elem->value;
949 }
Damien429d7192013-10-04 19:53:11 +0100950 } else {
951 assert(0);
952 }
953 } else if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
954 py_small_int_t val;
955 switch (op) {
956 case RT_BINARY_OP_ADD:
957 case RT_BINARY_OP_INPLACE_ADD: val = FROM_SMALL_INT(lhs) + FROM_SMALL_INT(rhs); break;
Damienbd254452013-10-16 20:39:12 +0100958 case RT_BINARY_OP_SUBTRACT:
959 case RT_BINARY_OP_INPLACE_SUBTRACT: val = FROM_SMALL_INT(lhs) - FROM_SMALL_INT(rhs); break;
Damien429d7192013-10-04 19:53:11 +0100960 case RT_BINARY_OP_MULTIPLY: val = FROM_SMALL_INT(lhs) * FROM_SMALL_INT(rhs); break;
961 case RT_BINARY_OP_FLOOR_DIVIDE: val = FROM_SMALL_INT(lhs) / FROM_SMALL_INT(rhs); break;
Damien3ef4abb2013-10-12 16:53:13 +0100962#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100963 case RT_BINARY_OP_TRUE_DIVIDE: return py_obj_new_float((float_t)FROM_SMALL_INT(lhs) / (float_t)FROM_SMALL_INT(rhs));
964#endif
965 default: printf("%d\n", op); assert(0); val = 0;
966 }
967 if (fit_small_int(val)) {
968 return TO_SMALL_INT(val);
969 }
970 } else if (IS_O(lhs, O_STR) && IS_O(rhs, O_STR)) {
971 const char *lhs_str = qstr_str(((py_obj_base_t*)lhs)->u_str);
972 const char *rhs_str = qstr_str(((py_obj_base_t*)rhs)->u_str);
973 char *val;
974 switch (op) {
975 case RT_BINARY_OP_ADD:
976 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;
977 default: printf("%d\n", op); assert(0); val = NULL;
978 }
979 return py_obj_new_str(qstr_from_str_take(val));
980 }
981 assert(0);
982 return py_const_none;
983}
984
985py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs) {
986 DEBUG_OP_printf("compare %d %p %p\n", op, lhs, rhs);
987 if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
988 int cmp;
989 switch (op) {
990 case RT_COMPARE_OP_LESS: cmp = FROM_SMALL_INT(lhs) < FROM_SMALL_INT(rhs); break;
991 case RT_COMPARE_OP_MORE: cmp = FROM_SMALL_INT(lhs) > FROM_SMALL_INT(rhs); break;
992 default: assert(0); cmp = 0;
993 }
994 if (cmp) {
995 return py_const_true;
996 } else {
997 return py_const_false;
998 }
999 }
1000 assert(0);
1001 return py_const_none;
1002}
1003
1004py_obj_t rt_make_function_from_id(int unique_code_id) {
Damienb05d7072013-10-05 13:37:10 +01001005 DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id);
1006 if (unique_code_id < 1 || unique_code_id >= next_unique_code_id) {
Damien429d7192013-10-04 19:53:11 +01001007 // illegal code id
1008 return py_const_none;
1009 }
1010 py_code_t *c = &unique_codes[unique_code_id];
1011 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1012 switch (c->kind) {
Damien826005c2013-10-05 23:17:28 +01001013 case PY_CODE_BYTE:
1014 o->kind = O_FUN_BC;
1015 o->u_fun_bc.n_args = c->n_args;
1016 o->u_fun_bc.code = c->u_byte.code;
1017 o->u_fun_bc.len = c->u_byte.len;
1018 break;
Damien429d7192013-10-04 19:53:11 +01001019 case PY_CODE_NATIVE:
1020 switch (c->n_args) {
1021 case 0: o->kind = O_FUN_0; break;
1022 case 1: o->kind = O_FUN_1; break;
1023 case 2: o->kind = O_FUN_2; break;
1024 default: assert(0);
1025 }
1026 o->u_fun.fun = c->u_native.fun;
1027 break;
Damien826005c2013-10-05 23:17:28 +01001028 case PY_CODE_INLINE_ASM:
1029 o->kind = O_FUN_ASM;
1030 o->u_fun_asm.n_args = c->n_args;
1031 o->u_fun_asm.fun = c->u_inline_asm.fun;
Damien429d7192013-10-04 19:53:11 +01001032 break;
1033 default:
1034 assert(0);
1035 }
Damienbd254452013-10-16 20:39:12 +01001036
1037 // check for generator functions and if so wrap in generator object
1038 if (c->is_generator) {
1039 py_obj_base_t *o2 = m_new(py_obj_base_t, 1);
1040 o2->kind = O_GEN_WRAP;
1041 // we have at least 3 locals so the bc can write back fast[0,1,2] safely; should improve how this is done
1042 o2->u_gen_wrap.n_state = (c->n_locals < 3 ? 3 : c->n_locals) + c->n_stack;
1043 o2->u_gen_wrap.fun = o;
1044 o = o2;
1045 }
1046
Damien429d7192013-10-04 19:53:11 +01001047 return o;
1048}
1049
1050py_obj_t rt_make_function_0(py_fun_0_t fun) {
1051 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1052 o->kind = O_FUN_0;
1053 o->u_fun.fun = fun;
1054 return o;
1055}
1056
1057py_obj_t rt_make_function_1(py_fun_1_t fun) {
1058 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1059 o->kind = O_FUN_1;
1060 o->u_fun.fun = fun;
1061 return o;
1062}
1063
1064py_obj_t rt_make_function_2(py_fun_2_t fun) {
1065 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1066 o->kind = O_FUN_2;
1067 o->u_fun.fun = fun;
1068 return o;
1069}
1070
1071py_obj_t rt_make_function(int n_args, py_fun_t code) {
1072 // assumes code is a pointer to a py_fun_t (i think this is safe...)
1073 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1074 o->kind = O_FUN_N;
Damien429d7192013-10-04 19:53:11 +01001075 o->u_fun.n_args = n_args;
Damien826005c2013-10-05 23:17:28 +01001076 o->u_fun.fun = code;
Damien429d7192013-10-04 19:53:11 +01001077 return o;
1078}
1079
Damieneb19efb2013-10-10 22:06:54 +01001080py_obj_t rt_call_function_0(py_obj_t fun) {
1081 return rt_call_function_n(fun, 0, NULL);
1082}
1083
1084py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) {
1085 return rt_call_function_n(fun, 1, &arg);
1086}
1087
1088py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) {
1089 py_obj_t args[2];
1090 args[1] = arg1;
1091 args[0] = arg2;
1092 return rt_call_function_n(fun, 2, args);
1093}
1094
1095typedef machine_uint_t (*inline_asm_fun_0_t)();
1096typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t);
1097typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t);
1098typedef machine_uint_t (*inline_asm_fun_3_t)(machine_uint_t, machine_uint_t, machine_uint_t);
1099
Damiene4af64f2013-10-06 12:04:13 +01001100// convert a Python object to a sensible value for inline asm
1101machine_uint_t rt_convert_obj_for_inline_asm(py_obj_t obj) {
1102 // TODO for byte_array, pass pointer to the array
1103 if (IS_SMALL_INT(obj)) {
1104 return FROM_SMALL_INT(obj);
1105 } else if (obj == py_const_none) {
1106 return 0;
1107 } else if (obj == py_const_false) {
1108 return 0;
1109 } else if (obj == py_const_true) {
1110 return 1;
1111 } else {
1112 py_obj_base_t *o = obj;
1113 switch (o->kind) {
1114 case O_STR:
1115 // pointer to the string (it's probably constant though!)
1116 return (machine_uint_t)qstr_str(o->u_str);
1117
Damien3ef4abb2013-10-12 16:53:13 +01001118#if MICROPY_ENABLE_FLOAT
Damiene4af64f2013-10-06 12:04:13 +01001119 case O_FLOAT:
1120 // convert float to int (could also pass in float registers)
1121 return (machine_int_t)o->u_flt;
Damienc025ebb2013-10-12 14:30:21 +01001122#endif
Damiene4af64f2013-10-06 12:04:13 +01001123
Damienc226dca2013-10-16 16:12:52 +01001124 case O_TUPLE:
Damiene4af64f2013-10-06 12:04:13 +01001125 case O_LIST:
Damienc226dca2013-10-16 16:12:52 +01001126 // pointer to start of tuple/list (could pass length, but then could use len(x) for that)
1127 return (machine_uint_t)o->u_tuple_list.items;
Damiene4af64f2013-10-06 12:04:13 +01001128
1129 default:
1130 // just pass along a pointer to the object
1131 return (machine_uint_t)obj;
1132 }
1133 }
1134}
1135
1136// convert a return value from inline asm to a sensible Python object
1137py_obj_t rt_convert_val_from_inline_asm(machine_uint_t val) {
1138 return TO_SMALL_INT(val);
1139}
1140
Damieneb19efb2013-10-10 22:06:54 +01001141// args are in reverse order in the array
1142py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args) {
1143 int n_args_fun = 0;
Damien429d7192013-10-04 19:53:11 +01001144 if (IS_O(fun, O_FUN_0)) {
1145 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001146 if (n_args != 0) {
1147 n_args_fun = 0;
1148 goto bad_n_args;
1149 }
1150 DEBUG_OP_printf("calling native %p()\n", o->u_fun.fun);
Damien429d7192013-10-04 19:53:11 +01001151 return ((py_fun_0_t)o->u_fun.fun)();
Damieneb19efb2013-10-10 22:06:54 +01001152
1153 } else if (IS_O(fun, O_FUN_1)) {
1154 py_obj_base_t *o = fun;
1155 if (n_args != 1) {
1156 n_args_fun = 1;
1157 goto bad_n_args;
1158 }
1159 DEBUG_OP_printf("calling native %p(%p)\n", o->u_fun.fun, args[0]);
1160 return ((py_fun_1_t)o->u_fun.fun)(args[0]);
1161
1162 } else if (IS_O(fun, O_FUN_2)) {
1163 py_obj_base_t *o = fun;
1164 if (n_args != 2) {
1165 n_args_fun = 2;
1166 goto bad_n_args;
1167 }
1168 DEBUG_OP_printf("calling native %p(%p, %p)\n", o->u_fun.fun, args[1], args[0]);
1169 return ((py_fun_2_t)o->u_fun.fun)(args[1], args[0]);
1170
1171 // TODO O_FUN_N
1172
Damien429d7192013-10-04 19:53:11 +01001173 } else if (IS_O(fun, O_FUN_BC)) {
1174 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001175 if (n_args != o->u_fun_bc.n_args) {
1176 n_args_fun = o->u_fun_bc.n_args;
1177 goto bad_n_args;
1178 }
1179 DEBUG_OP_printf("calling byte code %p(n_args=%d)\n", o->u_fun_bc.code, n_args);
Damienbd254452013-10-16 20:39:12 +01001180 return py_execute_byte_code(o->u_fun_bc.code, args, n_args);
Damieneb19efb2013-10-10 22:06:54 +01001181
Damiene4af64f2013-10-06 12:04:13 +01001182 } else if (IS_O(fun, O_FUN_ASM)) {
1183 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001184 if (n_args != o->u_fun_asm.n_args) {
1185 n_args_fun = o->u_fun_asm.n_args;
1186 goto bad_n_args;
1187 }
1188 DEBUG_OP_printf("calling inline asm %p(n_args=%d)\n", o->u_fun_asm.fun, n_args);
1189 machine_uint_t ret;
1190 if (n_args == 0) {
1191 ret = ((inline_asm_fun_0_t)o->u_fun_asm.fun)();
1192 } else if (n_args == 1) {
1193 ret = ((inline_asm_fun_1_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[0]));
1194 } else if (n_args == 2) {
1195 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]));
1196 } else if (n_args == 3) {
1197 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]));
1198 } else {
1199 assert(0);
1200 ret = 0;
1201 }
1202 return rt_convert_val_from_inline_asm(ret);
1203
Damienbd254452013-10-16 20:39:12 +01001204 } else if (IS_O(fun, O_GEN_WRAP)) {
1205 py_obj_base_t *o = fun;
1206 py_obj_base_t *o_fun = o->u_gen_wrap.fun;
1207 assert(o_fun->kind == O_FUN_BC); // TODO
1208 if (n_args != o_fun->u_fun_bc.n_args) {
1209 n_args_fun = o_fun->u_fun_bc.n_args;
1210 goto bad_n_args;
1211 }
1212 py_obj_t *state = m_new(py_obj_t, 1 + o->u_gen_wrap.n_state);
1213 // put function object at first slot in state (to keep u_gen_instance small)
1214 state[0] = o_fun;
1215 // init args
1216 for (int i = 0; i < n_args; i++) {
1217 state[1 + i] = args[n_args - 1 - i];
1218 }
1219 py_obj_base_t *o2 = m_new(py_obj_base_t, 1);
1220 o2->kind = O_GEN_INSTANCE;
1221 o2->u_gen_instance.state = state;
1222 o2->u_gen_instance.ip = o_fun->u_fun_bc.code;
1223 o2->u_gen_instance.sp = state + o->u_gen_wrap.n_state;
1224 return o2;
1225
Damiena3977762013-10-09 23:10:10 +01001226 } else if (IS_O(fun, O_BOUND_METH)) {
1227 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001228 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);
1229 if (n_args == 0) {
1230 return rt_call_function_n(o->u_bound_meth.meth, 1, &o->u_bound_meth.self);
1231 } else if (n_args == 1) {
1232 py_obj_t args2[2];
1233 args2[1] = o->u_bound_meth.self;
1234 args2[0] = args[0];
1235 return rt_call_function_n(o->u_bound_meth.meth, 2, args2);
1236 } else {
1237 // TODO not implemented
1238 assert(0);
1239 return py_const_none;
1240 //return rt_call_function_2(o->u_bound_meth.meth, n_args + 1, o->u_bound_meth.self + args);
1241 }
1242
Damiena3977762013-10-09 23:10:10 +01001243 } else if (IS_O(fun, O_CLASS)) {
1244 // instantiate an instance of a class
Damieneb19efb2013-10-10 22:06:54 +01001245 if (n_args != 0) {
1246 n_args_fun = 0;
1247 goto bad_n_args;
1248 }
Damiena3977762013-10-09 23:10:10 +01001249 DEBUG_OP_printf("instantiate object of class %p with no args\n", fun);
1250 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1251 o->kind = O_OBJ;
1252 o->u_obj.class = fun;
1253 o->u_obj.members = py_map_new(MAP_QSTR, 0);
1254 return o;
Damieneb19efb2013-10-10 22:06:54 +01001255
Damien429d7192013-10-04 19:53:11 +01001256 } else {
Damieneb19efb2013-10-10 22:06:54 +01001257 printf("fun %p %d\n", fun, ((py_obj_base_t*)fun)->kind);
Damien429d7192013-10-04 19:53:11 +01001258 assert(0);
1259 return py_const_none;
1260 }
Damien429d7192013-10-04 19:53:11 +01001261
Damieneb19efb2013-10-10 22:06:54 +01001262bad_n_args:
Damienbd254452013-10-16 20:39:12 +01001263 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 +01001264}
1265
Damiena3977762013-10-09 23:10:10 +01001266// args contains: arg(n_args-1) arg(n_args-2) ... arg(0) self/NULL fun
1267// if n_args==0 then there are only self/NULL and fun
1268py_obj_t rt_call_method_n(int n_args, const py_obj_t *args) {
Damien7f5dacf2013-10-10 11:24:39 +01001269 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 +01001270 return rt_call_function_n(args[n_args + 1], n_args + ((args[n_args] == NULL) ? 0 : 1), args);
1271}
1272
Damien429d7192013-10-04 19:53:11 +01001273// items are in reverse order
Damienc226dca2013-10-16 16:12:52 +01001274py_obj_t rt_build_tuple(int n_args, py_obj_t *items) {
1275 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1276 o->kind = O_TUPLE;
1277 o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args;
1278 o->u_tuple_list.len = n_args;
1279 o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc);
1280 for (int i = 0; i < n_args; i++) {
1281 o->u_tuple_list.items[i] = items[n_args - i - 1];
1282 }
1283 return o;
1284}
1285
1286// items are in reverse order
Damien429d7192013-10-04 19:53:11 +01001287py_obj_t rt_build_list(int n_args, py_obj_t *items) {
1288 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1289 o->kind = O_LIST;
Damienc226dca2013-10-16 16:12:52 +01001290 o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args;
1291 o->u_tuple_list.len = n_args;
1292 o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc);
Damien429d7192013-10-04 19:53:11 +01001293 for (int i = 0; i < n_args; i++) {
Damienc226dca2013-10-16 16:12:52 +01001294 o->u_tuple_list.items[i] = items[n_args - i - 1];
Damien429d7192013-10-04 19:53:11 +01001295 }
1296 return o;
1297}
1298
1299py_obj_t py_set_lookup(py_obj_t o_in, py_obj_t index, bool add_if_not_found) {
1300 assert(IS_O(o_in, O_SET));
1301 py_obj_base_t *o = o_in;
1302 int hash = py_obj_hash(index);
1303 int pos = hash % o->u_set.alloc;
1304 for (;;) {
1305 py_obj_t elem = o->u_set.table[pos];
1306 if (elem == NULL) {
1307 // not in table
1308 if (add_if_not_found) {
1309 if (o->u_set.used + 1 >= o->u_set.alloc) {
1310 // not enough room in table, rehash it
1311 int old_alloc = o->u_set.alloc;
1312 py_obj_t *old_table = o->u_set.table;
1313 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(o->u_set.alloc + 1);
1314 o->u_set.used = 0;
1315 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
1316 for (int i = 0; i < old_alloc; i++) {
1317 if (old_table[i] != NULL) {
1318 py_set_lookup(o, old_table[i], true);
1319 }
1320 }
1321 m_free(old_table);
1322 // restart the search for the new element
1323 pos = hash % o->u_set.alloc;
1324 } else {
1325 o->u_set.used += 1;
1326 o->u_set.table[pos] = index;
1327 return index;
1328 }
1329 } else {
1330 return NULL;
1331 }
1332 } else if (py_obj_equal(elem, index)) {
1333 // found it
1334 return elem;
1335 } else {
1336 // not yet found, keep searching in this table
1337 pos = (pos + 1) % o->u_set.alloc;
1338 }
1339 }
1340}
1341
1342py_obj_t rt_build_set(int n_args, py_obj_t *items) {
1343 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1344 o->kind = O_SET;
1345 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(n_args + 1);
1346 o->u_set.used = 0;
1347 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
1348 for (int i = 0; i < o->u_set.alloc; i++) {
1349 o->u_set.table[i] = NULL;
1350 }
1351 for (int i = 0; i < n_args; i++) {
1352 py_set_lookup(o, items[i], true);
1353 }
1354 return o;
1355}
1356
Damienc12aa462013-10-16 20:57:49 +01001357py_obj_t rt_store_set(py_obj_t set, py_obj_t item) {
1358 py_set_lookup(set, item, true);
1359 return set;
1360}
1361
Damien429d7192013-10-04 19:53:11 +01001362py_obj_t rt_build_map(int n_args) {
1363 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1364 o->kind = O_MAP;
1365 py_map_init(&o->u_map, MAP_PY_OBJ, n_args);
1366 return o;
1367}
1368
1369py_obj_t rt_store_map(py_obj_t map, py_obj_t key, py_obj_t value) {
1370 assert(IS_O(map, O_MAP)); // should always be
1371 py_map_lookup(map, key, true)->value = value;
1372 return map;
1373}
1374
Damiena3977762013-10-09 23:10:10 +01001375py_obj_t build_bound_method(py_obj_t self, py_obj_t meth) {
1376 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1377 o->kind = O_BOUND_METH;
1378 o->u_bound_meth.meth = meth;
1379 o->u_bound_meth.self = self;
1380 return o;
1381}
1382
1383py_obj_t rt_load_attr(py_obj_t base, qstr attr) {
1384 DEBUG_OP_printf("load attr %s\n", qstr_str(attr));
1385 if (IS_O(base, O_LIST) && attr == q_append) {
1386 return build_bound_method(base, fun_list_append);
1387 } else if (IS_O(base, O_CLASS)) {
1388 py_obj_base_t *o = base;
1389 py_map_elem_t *elem = py_qstr_map_lookup(o->u_class.locals, attr, false);
1390 if (elem == NULL) {
1391 goto no_attr;
1392 }
1393 return elem->value;
1394 } else if (IS_O(base, O_OBJ)) {
1395 // logic: look in obj members then class locals (TODO check this against CPython)
1396 py_obj_base_t *o = base;
1397 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false);
1398 if (elem != NULL) {
1399 // object member, always treated as a value
1400 return elem->value;
1401 }
1402 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1403 if (elem != NULL) {
1404 if (py_obj_is_callable(elem->value)) {
1405 // class member is callable so build a bound method
1406 return build_bound_method(base, elem->value);
1407 } else {
1408 // class member is a value, so just return that value
1409 return elem->value;
1410 }
1411 }
1412 goto no_attr;
1413 }
1414
1415no_attr:
Damience89a212013-10-15 22:25:17 +01001416 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 +01001417}
1418
1419void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest) {
1420 DEBUG_OP_printf("load method %s\n", qstr_str(attr));
Damienbd254452013-10-16 20:39:12 +01001421 if (IS_O(base, O_GEN_INSTANCE) && attr == q___next__) {
1422 dest[1] = fun_gen_instance_next;
1423 dest[0] = base;
1424 return;
1425 } else if (IS_O(base, O_LIST) && attr == q_append) {
Damiena3977762013-10-09 23:10:10 +01001426 dest[1] = fun_list_append;
1427 dest[0] = base;
1428 return;
1429 } else if (IS_O(base, O_OBJ)) {
1430 // logic: look in obj members then class locals (TODO check this against CPython)
1431 py_obj_base_t *o = base;
1432 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false);
1433 if (elem != NULL) {
1434 // object member, always treated as a value
1435 dest[1] = elem->value;
1436 dest[0] = NULL;
1437 return;
1438 }
1439 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1440 if (elem != NULL) {
1441 if (py_obj_is_callable(elem->value)) {
1442 // class member is callable so build a bound method
1443 dest[1] = elem->value;
1444 dest[0] = base;
1445 return;
1446 } else {
1447 // class member is a value, so just return that value
1448 dest[1] = elem->value;
1449 dest[0] = NULL;
1450 return;
1451 }
1452 }
1453 goto no_attr;
1454 }
1455
1456no_attr:
1457 dest[1] = rt_load_attr(base, attr);
1458 dest[0] = NULL;
1459}
1460
Damien5ac1b2e2013-10-18 19:58:12 +01001461void rt_store_attr(py_obj_t base, qstr attr, py_obj_t value) {
1462 DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value);
Damiena3977762013-10-09 23:10:10 +01001463 if (IS_O(base, O_OBJ)) {
1464 // logic: look in class locals (no add) then obj members (add) (TODO check this against CPython)
1465 py_obj_base_t *o = base;
1466 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1467 if (elem != NULL) {
Damien5ac1b2e2013-10-18 19:58:12 +01001468 elem->value = value;
Damiena3977762013-10-09 23:10:10 +01001469 } else {
Damien5ac1b2e2013-10-18 19:58:12 +01001470 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, true)->value = value;
Damiena3977762013-10-09 23:10:10 +01001471 }
1472 } else {
1473 printf("?AttributeError: '%s' object has no attribute '%s'\n", py_obj_get_type_str(base), qstr_str(attr));
1474 assert(0);
1475 }
1476}
1477
Damien429d7192013-10-04 19:53:11 +01001478void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t value) {
Damien5ac1b2e2013-10-18 19:58:12 +01001479 DEBUG_OP_printf("store subscr %p[%p] <- %p\n", base, index, value);
Damienc226dca2013-10-16 16:12:52 +01001480 if (IS_O(base, O_LIST)) {
Damien429d7192013-10-04 19:53:11 +01001481 // list store
Damienc226dca2013-10-16 16:12:52 +01001482 uint i = get_index(base, index);
1483 ((py_obj_base_t*)base)->u_tuple_list.items[i] = value;
Damien429d7192013-10-04 19:53:11 +01001484 } else if (IS_O(base, O_MAP)) {
1485 // map store
1486 py_map_lookup(base, index, true)->value = value;
1487 } else {
1488 assert(0);
1489 }
1490}
1491
Damience89a212013-10-15 22:25:17 +01001492py_obj_t rt_getiter(py_obj_t o_in) {
Damienbd254452013-10-16 20:39:12 +01001493 if (IS_O(o_in, O_GEN_INSTANCE)) {
1494 return o_in;
1495 } else if (IS_O(o_in, O_RANGE)) {
Damience89a212013-10-15 22:25:17 +01001496 py_obj_base_t *o = o_in;
1497 return py_obj_new_range_iterator(o->u_range.start, o->u_range.stop, o->u_range.step);
Damienc226dca2013-10-16 16:12:52 +01001498 } else if (IS_O(o_in, O_TUPLE)) {
1499 return py_obj_new_tuple_iterator(o_in, 0);
1500 } else if (IS_O(o_in, O_LIST)) {
1501 return py_obj_new_list_iterator(o_in, 0);
Damience89a212013-10-15 22:25:17 +01001502 } else {
1503 nlr_jump(py_obj_new_exception_2(q_TypeError, "'%s' object is not iterable", py_obj_get_type_str(o_in), NULL));
1504 }
1505}
1506
1507py_obj_t rt_iternext(py_obj_t o_in) {
Damienbd254452013-10-16 20:39:12 +01001508 if (IS_O(o_in, O_GEN_INSTANCE)) {
1509 py_obj_base_t *self = o_in;
1510 py_obj_base_t *fun = self->u_gen_instance.state[0];
1511 assert(fun->kind == O_FUN_BC);
1512 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);
1513 if (yield) {
1514 return *self->u_gen_instance.sp;
1515 } else {
1516 if (*self->u_gen_instance.sp == py_const_none) {
1517 return py_const_stop_iteration;
1518 } else {
1519 // TODO return StopIteration with value *self->u_gen_instance.sp
1520 return py_const_stop_iteration;
1521 }
1522 }
1523
1524 } else if (IS_O(o_in, O_RANGE_IT)) {
Damience89a212013-10-15 22:25:17 +01001525 py_obj_base_t *o = o_in;
1526 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)) {
1527 py_obj_t o_out = TO_SMALL_INT(o->u_range_it.cur);
1528 o->u_range_it.cur += o->u_range_it.step;
1529 return o_out;
1530 } else {
1531 return py_const_stop_iteration;
1532 }
Damienbd254452013-10-16 20:39:12 +01001533
Damienc226dca2013-10-16 16:12:52 +01001534 } else if (IS_O(o_in, O_TUPLE_IT) || IS_O(o_in, O_LIST_IT)) {
1535 py_obj_base_t *o = o_in;
1536 if (o->u_tuple_list_it.cur < o->u_tuple_list_it.obj->u_tuple_list.len) {
1537 py_obj_t o_out = o->u_tuple_list_it.obj->u_tuple_list.items[o->u_tuple_list_it.cur];
1538 o->u_tuple_list_it.cur += 1;
1539 return o_out;
1540 } else {
1541 return py_const_stop_iteration;
1542 }
Damienbd254452013-10-16 20:39:12 +01001543
Damience89a212013-10-15 22:25:17 +01001544 } else {
1545 nlr_jump(py_obj_new_exception_2(q_TypeError, "? '%s' object is not iterable", py_obj_get_type_str(o_in), NULL));
1546 }
1547}
1548
Damien429d7192013-10-04 19:53:11 +01001549void *rt_fun_table[RT_F_NUMBER_OF] = {
1550 rt_load_const_str,
1551 rt_load_name,
1552 rt_load_global,
Damien7f5dacf2013-10-10 11:24:39 +01001553 rt_load_build_class,
Damien429d7192013-10-04 19:53:11 +01001554 rt_load_attr,
1555 rt_load_method,
1556 rt_store_name,
Damien7f5dacf2013-10-10 11:24:39 +01001557 rt_store_attr,
Damien429d7192013-10-04 19:53:11 +01001558 rt_store_subscr,
1559 rt_is_true,
1560 rt_unary_op,
Damiend2755ec2013-10-16 23:58:48 +01001561 rt_build_tuple,
Damien429d7192013-10-04 19:53:11 +01001562 rt_build_list,
Damiend2755ec2013-10-16 23:58:48 +01001563 rt_list_append,
Damien429d7192013-10-04 19:53:11 +01001564 rt_build_map,
1565 rt_store_map,
1566 rt_build_set,
Damiend2755ec2013-10-16 23:58:48 +01001567 rt_store_set,
Damien429d7192013-10-04 19:53:11 +01001568 rt_make_function_from_id,
Damieneb19efb2013-10-10 22:06:54 +01001569 rt_call_function_n,
Damien7f5dacf2013-10-10 11:24:39 +01001570 rt_call_method_n,
Damien429d7192013-10-04 19:53:11 +01001571 rt_binary_op,
1572 rt_compare_op,
Damiend2755ec2013-10-16 23:58:48 +01001573 rt_getiter,
1574 rt_iternext,
Damien429d7192013-10-04 19:53:11 +01001575};
1576
1577/*
1578void rt_f_vector(rt_fun_kind_t fun_kind) {
1579 (rt_f_table[fun_kind])();
1580}
1581*/