blob: 6e60b36dbb6bc29b4ee266d0d4e7362c9fbae60b [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>
Damien96a0add2013-11-03 18:30:10 +00008#include <stdarg.h>
Damien429d7192013-10-04 19:53:11 +01009#include <string.h>
10#include <assert.h>
11
Damience89a212013-10-15 22:25:17 +010012#include "nlr.h"
Damien429d7192013-10-04 19:53:11 +010013#include "misc.h"
Damienc025ebb2013-10-12 14:30:21 +010014#include "mpyconfig.h"
Damien429d7192013-10-04 19:53:11 +010015#include "runtime.h"
Damieneb19efb2013-10-10 22:06:54 +010016#include "bc.h"
Damien429d7192013-10-04 19:53:11 +010017
Damien7410e442013-11-02 19:47:57 +000018#if MICROPY_ENABLE_FLOAT
19// for sqrt
20#include <math.h>
21#endif
22
Damien7f5dacf2013-10-10 11:24:39 +010023#if 0 // print debugging info
Damiena1ddfcc2013-10-10 23:25:50 +010024#define DEBUG_PRINT (1)
25#define WRITE_NATIVE (1)
Damien7f5dacf2013-10-10 11:24:39 +010026#define DEBUG_printf(args...) printf(args)
27#define DEBUG_OP_printf(args...) printf(args)
28#else // don't print debugging info
Damiena3977762013-10-09 23:10:10 +010029#define DEBUG_printf(args...) (void)0
Damien429d7192013-10-04 19:53:11 +010030#define DEBUG_OP_printf(args...) (void)0
Damien7f5dacf2013-10-10 11:24:39 +010031#endif
Damien429d7192013-10-04 19:53:11 +010032
Damien429d7192013-10-04 19:53:11 +010033typedef machine_int_t py_small_int_t;
34
35#define IS_O(o, k) (((((py_small_int_t)(o)) & 1) == 0) && (((py_obj_base_t*)(o))->kind == (k)))
36#define IS_SMALL_INT(o) (((py_small_int_t)(o)) & 1)
37#define FROM_SMALL_INT(o) (((py_small_int_t)(o)) >> 1)
38#define TO_SMALL_INT(o) ((py_obj_t)(((o) << 1) | 1))
39
Damien3ef4abb2013-10-12 16:53:13 +010040#if MICROPY_ENABLE_FLOAT
Damien7410e442013-11-02 19:47:57 +000041typedef machine_float_t py_float_t;
Damien429d7192013-10-04 19:53:11 +010042#endif
43
44typedef enum {
45 O_CONST,
46 O_STR,
Damien3ef4abb2013-10-12 16:53:13 +010047#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +010048 O_FLOAT,
Damien7410e442013-11-02 19:47:57 +000049 O_COMPLEX,
Damien429d7192013-10-04 19:53:11 +010050#endif
Damience89a212013-10-15 22:25:17 +010051 O_EXCEPTION_0,
Damienf086ecf2013-10-22 16:05:11 +010052 O_EXCEPTION_N,
Damience89a212013-10-15 22:25:17 +010053 O_RANGE,
54 O_RANGE_IT,
Damien429d7192013-10-04 19:53:11 +010055 O_FUN_0,
56 O_FUN_1,
57 O_FUN_2,
58 O_FUN_N,
Damien2f06c572013-11-03 18:20:56 +000059 O_FUN_VAR,
Damien429d7192013-10-04 19:53:11 +010060 O_FUN_BC,
Damien826005c2013-10-05 23:17:28 +010061 O_FUN_ASM,
Damienbd254452013-10-16 20:39:12 +010062 O_GEN_WRAP,
63 O_GEN_INSTANCE,
Damien429d7192013-10-04 19:53:11 +010064 O_BOUND_METH,
Damienc226dca2013-10-16 16:12:52 +010065 O_TUPLE,
Damien429d7192013-10-04 19:53:11 +010066 O_LIST,
Damienc226dca2013-10-16 16:12:52 +010067 O_TUPLE_IT,
68 O_LIST_IT,
Damien429d7192013-10-04 19:53:11 +010069 O_SET,
70 O_MAP,
71 O_CLASS,
Damiena3977762013-10-09 23:10:10 +010072 O_OBJ,
Damiend57eba52013-11-02 23:58:14 +000073 O_USER,
Damien429d7192013-10-04 19:53:11 +010074} py_obj_kind_t;
75
76typedef enum {
77 MAP_QSTR,
78 MAP_PY_OBJ,
79} py_map_kind_t;
80
81typedef struct _py_map_elem_t {
82 py_obj_t key;
83 py_obj_t value;
84} py_map_elem_t;
85
86typedef struct _py_map_t {
Damienf086ecf2013-10-22 16:05:11 +010087 struct {
88 py_map_kind_t kind : 1;
89 machine_uint_t used : (8 * BYTES_PER_WORD - 1);
90 };
Damien429d7192013-10-04 19:53:11 +010091 machine_uint_t alloc;
Damien429d7192013-10-04 19:53:11 +010092 py_map_elem_t *table;
93} py_map_t;
94
Damiena3977762013-10-09 23:10:10 +010095typedef struct _py_obj_base_t py_obj_base_t;
96
97struct _py_obj_base_t {
Damien429d7192013-10-04 19:53:11 +010098 py_obj_kind_t kind;
99 union {
100 const char *id;
101 qstr u_str;
Damien3ef4abb2013-10-12 16:53:13 +0100102#if MICROPY_ENABLE_FLOAT
Damien7410e442013-11-02 19:47:57 +0000103 py_float_t u_float; // for O_FLOAT
104 struct { // for O_COMPLEX
105 py_float_t real;
106 py_float_t imag;
107 } u_complex;
Damien429d7192013-10-04 19:53:11 +0100108#endif
Damience89a212013-10-15 22:25:17 +0100109 struct { // for O_EXCEPTION_0
110 qstr id;
111 } u_exc0;
Damienf086ecf2013-10-22 16:05:11 +0100112 struct { // for O_EXCEPTION_N
113 // TODO make generic object or something
Damience89a212013-10-15 22:25:17 +0100114 qstr id;
Damienf086ecf2013-10-22 16:05:11 +0100115 int n_args;
116 const void **args;
117 } u_exc_n;
Damience89a212013-10-15 22:25:17 +0100118 struct { // for O_RANGE
119 // TODO make generic object or something
120 machine_int_t start;
121 machine_int_t stop;
122 machine_int_t step;
123 } u_range;
124 struct { // for O_RANGE_IT
125 // TODO make generic object or something
126 machine_int_t cur;
127 machine_int_t stop;
128 machine_int_t step;
129 } u_range_it;
Damien2f06c572013-11-03 18:20:56 +0000130 struct { // for O_FUN_[012N], O_FUN_VAR
Damien429d7192013-10-04 19:53:11 +0100131 int n_args;
Damien826005c2013-10-05 23:17:28 +0100132 void *fun;
Damien429d7192013-10-04 19:53:11 +0100133 } u_fun;
134 struct { // for O_FUN_BC
Damien826005c2013-10-05 23:17:28 +0100135 int n_args;
Damien429d7192013-10-04 19:53:11 +0100136 byte *code;
137 uint len;
Damien429d7192013-10-04 19:53:11 +0100138 } u_fun_bc;
Damien826005c2013-10-05 23:17:28 +0100139 struct { // for O_FUN_ASM
140 int n_args;
141 void *fun;
142 } u_fun_asm;
Damienbd254452013-10-16 20:39:12 +0100143 struct { // for O_GEN_WRAP
144 int n_state;
145 py_obj_base_t *fun;
146 } u_gen_wrap;
147 struct { // for O_GEN_INSTANCE
148 py_obj_t *state;
149 const byte *ip;
150 py_obj_t *sp;
151 } u_gen_instance;
Damien429d7192013-10-04 19:53:11 +0100152 struct { // for O_BOUND_METH
153 py_obj_t meth;
154 py_obj_t self;
155 } u_bound_meth;
Damienc226dca2013-10-16 16:12:52 +0100156 struct { // for O_TUPLE, O_LIST
Damienf086ecf2013-10-22 16:05:11 +0100157 machine_uint_t alloc;
158 machine_uint_t len;
Damien429d7192013-10-04 19:53:11 +0100159 py_obj_t *items;
Damienc226dca2013-10-16 16:12:52 +0100160 } u_tuple_list;
161 struct { // for O_TUPLE_IT, O_LIST_IT
162 py_obj_base_t *obj;
Damienf086ecf2013-10-22 16:05:11 +0100163 machine_uint_t cur;
Damienc226dca2013-10-16 16:12:52 +0100164 } u_tuple_list_it;
Damien429d7192013-10-04 19:53:11 +0100165 struct { // for O_SET
Damienf086ecf2013-10-22 16:05:11 +0100166 machine_uint_t alloc;
167 machine_uint_t used;
Damien429d7192013-10-04 19:53:11 +0100168 py_obj_t *table;
169 } u_set;
170 py_map_t u_map; // for O_MAP
Damien429d7192013-10-04 19:53:11 +0100171 struct { // for O_CLASS
Damiena3977762013-10-09 23:10:10 +0100172 py_map_t *locals;
Damien429d7192013-10-04 19:53:11 +0100173 } u_class;
Damiena3977762013-10-09 23:10:10 +0100174 struct { // for O_OBJ
175 py_obj_base_t *class; // points to a O_CLASS object
176 py_map_t *members;
177 } u_obj;
Damiend57eba52013-11-02 23:58:14 +0000178 struct { // for O_USER
179 const py_user_info_t *info;
180 machine_uint_t data1;
181 machine_uint_t data2;
182 } u_user;
Damien429d7192013-10-04 19:53:11 +0100183 };
Damiena3977762013-10-09 23:10:10 +0100184};
Damien429d7192013-10-04 19:53:11 +0100185
Damien4ebb32f2013-11-02 14:33:10 +0000186static qstr q_append;
187static qstr q_join;
Damien2f06c572013-11-03 18:20:56 +0000188static qstr q_format;
Damien4ebb32f2013-11-02 14:33:10 +0000189static qstr q___build_class__;
190static qstr q___next__;
191static qstr q_AttributeError;
192static qstr q_IndexError;
193static qstr q_KeyError;
194static qstr q_NameError;
195static qstr q_TypeError;
Damien7410e442013-11-02 19:47:57 +0000196static qstr q_SyntaxError;
Damien4ebb32f2013-11-02 14:33:10 +0000197
Damien429d7192013-10-04 19:53:11 +0100198py_obj_t py_const_none;
199py_obj_t py_const_false;
200py_obj_t py_const_true;
Damience89a212013-10-15 22:25:17 +0100201py_obj_t py_const_stop_iteration;
Damien429d7192013-10-04 19:53:11 +0100202
Damieneb19efb2013-10-10 22:06:54 +0100203// locals and globals need to be pointers because they can be the same in outer module scope
Damien4ebb32f2013-11-02 14:33:10 +0000204static py_map_t *map_locals;
205static py_map_t *map_globals;
206static py_map_t map_builtins;
Damien429d7192013-10-04 19:53:11 +0100207
208// approximatelly doubling primes; made with Mathematica command: Table[Prime[Floor[(1.7)^n]], {n, 3, 24}]
209static 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};
210
211int get_doubling_prime_greater_or_equal_to(int x) {
212 for (int i = 0; i < sizeof(doubling_primes) / sizeof(int); i++) {
213 if (doubling_primes[i] >= x) {
214 return doubling_primes[i];
215 }
216 }
217 // ran out of primes in the table!
218 // return something sensible, at least make it odd
219 return x | 1;
220}
221
222void py_map_init(py_map_t *map, py_map_kind_t kind, int n) {
223 map->kind = kind;
Damien429d7192013-10-04 19:53:11 +0100224 map->used = 0;
Damienf086ecf2013-10-22 16:05:11 +0100225 map->alloc = get_doubling_prime_greater_or_equal_to(n + 1);
Damien5ac1b2e2013-10-18 19:58:12 +0100226 map->table = m_new0(py_map_elem_t, map->alloc);
Damien429d7192013-10-04 19:53:11 +0100227}
228
229py_map_t *py_map_new(py_map_kind_t kind, int n) {
230 py_map_t *map = m_new(py_map_t, 1);
231 py_map_init(map, kind, n);
232 return map;
233}
234
Damien5ac1b2e2013-10-18 19:58:12 +0100235machine_int_t py_obj_hash(py_obj_t o_in) {
236 if (o_in == py_const_false) {
237 return 0; // needs to hash to same as the integer 0, since False==0
238 } else if (o_in == py_const_true) {
239 return 1; // needs to hash to same as the integer 1, since True==1
240 } else if (IS_SMALL_INT(o_in)) {
Damien429d7192013-10-04 19:53:11 +0100241 return FROM_SMALL_INT(o_in);
Damien5ac1b2e2013-10-18 19:58:12 +0100242 } else if (IS_O(o_in, O_CONST)) {
243 return (machine_int_t)o_in;
Damien429d7192013-10-04 19:53:11 +0100244 } else if (IS_O(o_in, O_STR)) {
245 return ((py_obj_base_t*)o_in)->u_str;
246 } else {
247 assert(0);
248 return 0;
249 }
250}
251
Damien5ac1b2e2013-10-18 19:58:12 +0100252// this function implements the '==' operator (and so the inverse of '!=')
253// from the python language reference:
254// "The objects need not have the same type. If both are numbers, they are converted
255// to a common type. Otherwise, the == and != operators always consider objects of
256// different types to be unequal."
257// note also that False==0 and True==1 are true expressions
Damien429d7192013-10-04 19:53:11 +0100258bool py_obj_equal(py_obj_t o1, py_obj_t o2) {
259 if (o1 == o2) {
260 return true;
Damien5ac1b2e2013-10-18 19:58:12 +0100261 } else if (IS_SMALL_INT(o1) || IS_SMALL_INT(o2)) {
262 if (IS_SMALL_INT(o1) && IS_SMALL_INT(o2)) {
263 return false;
264 } else {
265 if (IS_SMALL_INT(o2)) {
266 py_obj_t temp = o1; o1 = o2; o2 = temp;
267 }
268 // o1 is the SMALL_INT, o2 is not
269 py_small_int_t val = FROM_SMALL_INT(o1);
270 if (o2 == py_const_false) {
271 return val == 0;
272 } else if (o2 == py_const_true) {
273 return val == 1;
274 } else {
275 return false;
276 }
277 }
Damien429d7192013-10-04 19:53:11 +0100278 } else if (IS_O(o1, O_STR) && IS_O(o2, O_STR)) {
279 return ((py_obj_base_t*)o1)->u_str == ((py_obj_base_t*)o2)->u_str;
280 } else {
281 assert(0);
282 return false;
283 }
284}
285
286py_map_elem_t* py_map_lookup_helper(py_map_t *map, py_obj_t index, bool add_if_not_found) {
287 bool is_map_py_obj = (map->kind == MAP_PY_OBJ);
288 machine_uint_t hash;
289 if (is_map_py_obj) {
290 hash = py_obj_hash(index);
291 } else {
292 hash = (machine_uint_t)index;
293 }
294 uint pos = hash % map->alloc;
295 for (;;) {
296 py_map_elem_t *elem = &map->table[pos];
297 if (elem->key == NULL) {
298 // not in table
299 if (add_if_not_found) {
300 if (map->used + 1 >= map->alloc) {
301 // not enough room in table, rehash it
302 int old_alloc = map->alloc;
303 py_map_elem_t *old_table = map->table;
304 map->alloc = get_doubling_prime_greater_or_equal_to(map->alloc + 1);
305 map->used = 0;
Damien5ac1b2e2013-10-18 19:58:12 +0100306 map->table = m_new0(py_map_elem_t, map->alloc);
Damien429d7192013-10-04 19:53:11 +0100307 for (int i = 0; i < old_alloc; i++) {
308 if (old_table[i].key != NULL) {
309 py_map_lookup_helper(map, old_table[i].key, true)->value = old_table[i].value;
310 }
311 }
312 m_free(old_table);
313 // restart the search for the new element
314 pos = hash % map->alloc;
315 } else {
316 map->used += 1;
317 elem->key = index;
318 return elem;
319 }
320 } else {
321 return NULL;
322 }
323 } else if (elem->key == index || (is_map_py_obj && py_obj_equal(elem->key, index))) {
324 // found it
Damien5ac1b2e2013-10-18 19:58:12 +0100325 /* it seems CPython does not replace the index; try x={True:'true'};x[1]='one';x
Damien429d7192013-10-04 19:53:11 +0100326 if (add_if_not_found) {
327 elem->key = index;
328 }
Damien5ac1b2e2013-10-18 19:58:12 +0100329 */
Damien429d7192013-10-04 19:53:11 +0100330 return elem;
331 } else {
332 // not yet found, keep searching in this table
333 pos = (pos + 1) % map->alloc;
334 }
335 }
336}
337
338py_map_elem_t* py_qstr_map_lookup(py_map_t *map, qstr index, bool add_if_not_found) {
339 py_obj_t o = (py_obj_t)(machine_uint_t)index;
340 return py_map_lookup_helper(map, o, add_if_not_found);
341}
342
343py_map_elem_t* py_map_lookup(py_obj_t o, py_obj_t index, bool add_if_not_found) {
344 assert(IS_O(o, O_MAP));
345 return py_map_lookup_helper(&((py_obj_base_t *)o)->u_map, index, add_if_not_found);
346}
347
348static bool fit_small_int(py_small_int_t o) {
349 return true;
350}
351
Damien4ebb32f2013-11-02 14:33:10 +0000352py_obj_t py_obj_new_int(machine_int_t value) {
Damien6f08f8c2013-10-23 22:17:26 +0100353 return TO_SMALL_INT(value);
354}
355
Damien429d7192013-10-04 19:53:11 +0100356py_obj_t py_obj_new_const(const char *id) {
357 py_obj_base_t *o = m_new(py_obj_base_t, 1);
358 o->kind = O_CONST;
359 o->id = id;
360 return (py_obj_t)o;
361}
362
363py_obj_t py_obj_new_str(qstr qstr) {
364 py_obj_base_t *o = m_new(py_obj_base_t, 1);
365 o->kind = O_STR;
366 o->u_str = qstr;
367 return (py_obj_t)o;
368}
369
Damien3ef4abb2013-10-12 16:53:13 +0100370#if MICROPY_ENABLE_FLOAT
Damien7410e442013-11-02 19:47:57 +0000371py_obj_t py_obj_new_float(py_float_t val) {
Damien429d7192013-10-04 19:53:11 +0100372 py_obj_base_t *o = m_new(py_obj_base_t, 1);
373 o->kind = O_FLOAT;
Damien7410e442013-11-02 19:47:57 +0000374 o->u_float = val;
375 return (py_obj_t)o;
376}
377
378py_obj_t py_obj_new_complex(py_float_t real, py_float_t imag) {
379 py_obj_base_t *o = m_new(py_obj_base_t, 1);
380 o->kind = O_COMPLEX;
381 o->u_complex.real = real;
382 o->u_complex.imag = imag;
Damien429d7192013-10-04 19:53:11 +0100383 return (py_obj_t)o;
384}
385#endif
386
Damience89a212013-10-15 22:25:17 +0100387py_obj_t py_obj_new_exception_0(qstr id) {
388 py_obj_base_t *o = m_new(py_obj_base_t, 1);
389 o->kind = O_EXCEPTION_0;
390 o->u_exc0.id = id;
391 return (py_obj_t)o;
392}
393
394py_obj_t py_obj_new_exception_2(qstr id, const char *fmt, const char *s1, const char *s2) {
395 py_obj_base_t *o = m_new(py_obj_base_t, 1);
Damienf086ecf2013-10-22 16:05:11 +0100396 o->kind = O_EXCEPTION_N;
397 o->u_exc_n.id = id;
398 o->u_exc_n.n_args = 3;
399 o->u_exc_n.args = m_new(const void*, 3);
400 o->u_exc_n.args[0] = fmt;
401 o->u_exc_n.args[1] = s1;
402 o->u_exc_n.args[2] = s2;
Damience89a212013-10-15 22:25:17 +0100403 return (py_obj_t)o;
404}
405
406// range is a class and instances are immutable sequence objects
407py_obj_t py_obj_new_range(int start, int stop, int step) {
408 py_obj_base_t *o = m_new(py_obj_base_t, 1);
409 o->kind = O_RANGE;
410 o->u_range.start = start;
411 o->u_range.stop = stop;
412 o->u_range.step = step;
413 return o;
414}
415
416py_obj_t py_obj_new_range_iterator(int cur, int stop, int step) {
417 py_obj_base_t *o = m_new(py_obj_base_t, 1);
418 o->kind = O_RANGE_IT;
419 o->u_range_it.cur = cur;
420 o->u_range_it.stop = stop;
421 o->u_range_it.step = step;
422 return o;
423}
424
Damienc226dca2013-10-16 16:12:52 +0100425py_obj_t py_obj_new_tuple_iterator(py_obj_base_t *tuple, int cur) {
426 py_obj_base_t *o = m_new(py_obj_base_t, 1);
427 o->kind = O_TUPLE_IT;
428 o->u_tuple_list_it.obj = tuple;
429 o->u_tuple_list_it.cur = cur;
430 return o;
431}
432
433py_obj_t py_obj_new_list_iterator(py_obj_base_t *list, int cur) {
434 py_obj_base_t *o = m_new(py_obj_base_t, 1);
435 o->kind = O_LIST_IT;
436 o->u_tuple_list_it.obj = list;
437 o->u_tuple_list_it.cur = cur;
438 return o;
439}
440
Damiend57eba52013-11-02 23:58:14 +0000441py_obj_t py_obj_new_user(const py_user_info_t *info, machine_uint_t data1, machine_uint_t data2) {
442 py_obj_base_t *o = m_new(py_obj_base_t, 1);
443 o->kind = O_USER;
444 // TODO should probably parse the info to turn strings to qstr's, and wrap functions in O_FUN_N objects
445 // that'll take up some memory. maybe we can lazily do the O_FUN_N: leave it a ptr to a C function, and
446 // only when the method is looked-up do we change that to the O_FUN_N object.
447 o->u_user.info = info;
448 o->u_user.data1 = data1;
449 o->u_user.data2 = data2;
450 return o;
451}
452
Damien33af3bf2013-11-03 14:39:47 +0000453const char *py_obj_get_type_str(py_obj_t o_in) {
454 if (IS_SMALL_INT(o_in)) {
455 return "int";
456 } else {
457 py_obj_base_t *o = o_in;
458 switch (o->kind) {
459 case O_CONST:
460 if (o == py_const_none) {
461 return "NoneType";
462 } else {
463 return "bool";
464 }
465 case O_STR:
466 return "str";
467#if MICROPY_ENABLE_FLOAT
468 case O_FLOAT:
469 return "float";
470#endif
471 case O_FUN_0:
472 case O_FUN_1:
473 case O_FUN_2:
474 case O_FUN_N:
Damien2f06c572013-11-03 18:20:56 +0000475 case O_FUN_VAR:
Damien33af3bf2013-11-03 14:39:47 +0000476 case O_FUN_BC:
477 return "function";
478 case O_GEN_INSTANCE:
479 return "generator";
480 case O_TUPLE:
481 return "tuple";
482 case O_LIST:
483 return "list";
484 case O_TUPLE_IT:
485 return "tuple_iterator";
486 case O_LIST_IT:
487 return "list_iterator";
488 case O_SET:
489 return "set";
490 case O_MAP:
491 return "dict";
492 case O_OBJ:
493 {
494 py_map_elem_t *qn = py_qstr_map_lookup(o->u_obj.class->u_class.locals, qstr_from_str_static("__qualname__"), false);
495 assert(qn != NULL);
496 assert(IS_O(qn->value, O_STR));
497 return qstr_str(((py_obj_base_t*)qn->value)->u_str);
498 }
499 case O_USER:
500 return o->u_user.info->type_name;
501 default:
502 assert(0);
503 return "UnknownType";
504 }
505 }
506}
507
508int rt_is_true(py_obj_t arg) {
509 DEBUG_OP_printf("is true %p\n", arg);
510 if (IS_SMALL_INT(arg)) {
511 if (FROM_SMALL_INT(arg) == 0) {
512 return 0;
513 } else {
514 return 1;
515 }
516 } else if (arg == py_const_none) {
517 return 0;
518 } else if (arg == py_const_false) {
519 return 0;
520 } else if (arg == py_const_true) {
521 return 1;
522 } else {
523 assert(0);
524 return 0;
525 }
526}
527
528machine_int_t py_obj_get_int(py_obj_t arg) {
529 if (arg == py_const_false) {
530 return 0;
531 } else if (arg == py_const_true) {
532 return 1;
533 } else if (IS_SMALL_INT(arg)) {
534 return FROM_SMALL_INT(arg);
535 } else {
536 assert(0);
537 return 0;
538 }
539}
540
541#if MICROPY_ENABLE_FLOAT
542machine_float_t py_obj_get_float(py_obj_t arg) {
543 if (arg == py_const_false) {
544 return 0;
545 } else if (arg == py_const_true) {
546 return 1;
547 } else if (IS_SMALL_INT(arg)) {
548 return FROM_SMALL_INT(arg);
549 } else if (IS_O(arg, O_FLOAT)) {
550 return ((py_obj_base_t*)arg)->u_float;
551 } else {
552 assert(0);
553 return 0;
554 }
555}
556
557void py_obj_get_complex(py_obj_t arg, py_float_t *real, py_float_t *imag) {
558 if (arg == py_const_false) {
559 *real = 0;
560 *imag = 0;
561 } else if (arg == py_const_true) {
562 *real = 1;
563 *imag = 0;
564 } else if (IS_SMALL_INT(arg)) {
565 *real = FROM_SMALL_INT(arg);
566 *imag = 0;
567 } else if (IS_O(arg, O_FLOAT)) {
568 *real = ((py_obj_base_t*)arg)->u_float;
569 *imag = 0;
570 } else if (IS_O(arg, O_COMPLEX)) {
571 *real = ((py_obj_base_t*)arg)->u_complex.real;
572 *imag = ((py_obj_base_t*)arg)->u_complex.imag;
573 } else {
574 assert(0);
575 *real = 0;
576 *imag = 0;
577 }
578}
579#endif
580
581qstr py_obj_get_qstr(py_obj_t arg) {
582 if (IS_O(arg, O_STR)) {
583 return ((py_obj_base_t*)arg)->u_str;
584 } else {
585 assert(0);
586 return 0;
587 }
588}
589
590py_obj_t *py_obj_get_array_fixed_n(py_obj_t o_in, machine_int_t n) {
591 if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) {
592 py_obj_base_t *o = o_in;
593 if (o->u_tuple_list.len != n) {
594 nlr_jump(py_obj_new_exception_2(q_IndexError, "requested length %d but object has length %d", (void*)n, (void*)o->u_tuple_list.len));
595 }
596 return o->u_tuple_list.items;
597 } else {
598 nlr_jump(py_obj_new_exception_2(q_TypeError, "object '%s' is not a tuple or list", py_obj_get_type_str(o_in), NULL));
599 }
600}
601
Damiend57eba52013-11-02 23:58:14 +0000602void py_user_get_data(py_obj_t o, machine_uint_t *data1, machine_uint_t *data2) {
603 assert(IS_O(o, O_USER));
604 if (data1 != NULL) {
605 *data1 = ((py_obj_base_t*)o)->u_user.data1;
606 }
607 if (data2 != NULL) {
608 *data2 = ((py_obj_base_t*)o)->u_user.data2;
609 }
610}
611
612void py_user_set_data(py_obj_t o, machine_uint_t data1, machine_uint_t data2) {
613 assert(IS_O(o, O_USER));
614 ((py_obj_base_t*)o)->u_user.data1 = data1;
615 ((py_obj_base_t*)o)->u_user.data2 = data2;
616}
617
Damien2f06c572013-11-03 18:20:56 +0000618void printf_wrapper(void *env, const char *fmt, ...) {
619 va_list args;
620 va_start(args, fmt);
621 vprintf(fmt, args);
622 va_end(args);
623}
624
625void vstr_printf_wrapper(void *env, const char *fmt, ...) {
626 va_list args;
627 va_start(args, fmt);
628 vstr_vprintf(env, fmt, args);
629 va_end(args);
630}
631
632void py_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, py_obj_t o_in) {
633 if (IS_SMALL_INT(o_in)) {
634 print(env, "%d", (int)FROM_SMALL_INT(o_in));
635 } else {
636 py_obj_base_t *o = o_in;
637 switch (o->kind) {
638 case O_CONST:
639 print(env, "%s", o->id);
640 break;
641 case O_STR:
642 // TODO need to escape chars etc
643 print(env, "'%s'", qstr_str(o->u_str));
644 break;
645#if MICROPY_ENABLE_FLOAT
646 case O_FLOAT:
647 print(env, "%.8g", o->u_float);
648 break;
649 case O_COMPLEX:
650 if (o->u_complex.real == 0) {
651 print(env, "%.8gj", o->u_complex.imag);
652 } else {
653 print(env, "(%.8g+%.8gj)", o->u_complex.real, o->u_complex.imag);
654 }
655 break;
656#endif
657 case O_EXCEPTION_0:
658 print(env, "%s", qstr_str(o->u_exc0.id));
659 break;
660 case O_EXCEPTION_N:
661 print(env, "%s: ", qstr_str(o->u_exc_n.id));
662 print(env, o->u_exc_n.args[0], o->u_exc_n.args[1], o->u_exc_n.args[2]);
663 break;
664 case O_GEN_INSTANCE:
665 print(env, "<generator object 'fun-name' at %p>", o);
666 break;
667 case O_TUPLE:
668 print(env, "(");
669 for (int i = 0; i < o->u_tuple_list.len; i++) {
670 if (i > 0) {
671 print(env, ", ");
672 }
673 py_obj_print_helper(print, env, o->u_tuple_list.items[i]);
674 }
675 if (o->u_tuple_list.len == 1) {
676 print(env, ",");
677 }
678 print(env, ")");
679 break;
680 case O_LIST:
681 print(env, "[");
682 for (int i = 0; i < o->u_tuple_list.len; i++) {
683 if (i > 0) {
684 print(env, ", ");
685 }
686 py_obj_print_helper(print, env, o->u_tuple_list.items[i]);
687 }
688 print(env, "]");
689 break;
690 case O_SET:
691 {
692 bool first = true;
693 print(env, "{");
694 for (int i = 0; i < o->u_set.alloc; i++) {
695 if (o->u_set.table[i] != NULL) {
696 if (!first) {
697 print(env, ", ");
698 }
699 first = false;
700 py_obj_print_helper(print, env, o->u_set.table[i]);
701 }
702 }
703 print(env, "}");
704 break;
705 }
706 case O_MAP:
707 {
708 bool first = true;
709 print(env, "{");
710 for (int i = 0; i < o->u_map.alloc; i++) {
711 if (o->u_map.table[i].key != NULL) {
712 if (!first) {
713 print(env, ", ");
714 }
715 first = false;
716 py_obj_print_helper(print, env, o->u_map.table[i].key);
717 print(env, ": ");
718 py_obj_print_helper(print, env, o->u_map.table[i].value);
719 }
720 }
721 print(env, "}");
722 break;
723 }
724 case O_USER:
725 o->u_user.info->print(o_in);
726 break;
727 default:
728 print(env, "<? %d>", o->kind);
729 assert(0);
730 }
731 }
732}
733
Damien4ebb32f2013-11-02 14:33:10 +0000734py_obj_t rt_str_join(py_obj_t self_in, py_obj_t arg) {
735 assert(IS_O(self_in, O_STR));
736 py_obj_base_t *self = self_in;
737 int required_len = strlen(qstr_str(self->u_str));
738
739 // process arg, count required chars
740 if (!IS_O(arg, O_TUPLE) && !IS_O(arg, O_LIST)) {
741 goto bad_arg;
742 }
743 py_obj_base_t *tuple_list = arg;
744 for (int i = 0; i < tuple_list->u_tuple_list.len; i++) {
745 if (!IS_O(tuple_list->u_tuple_list.items[i], O_STR)) {
746 goto bad_arg;
747 }
748 required_len += strlen(qstr_str(((py_obj_base_t*)tuple_list->u_tuple_list.items[i])->u_str));
749 }
750
751 // make joined string
752 char *joined_str = m_new(char, required_len + 1);
753 joined_str[0] = 0;
754 for (int i = 0; i < tuple_list->u_tuple_list.len; i++) {
755 const char *s2 = qstr_str(((py_obj_base_t*)tuple_list->u_tuple_list.items[i])->u_str);
756 if (i > 0) {
757 strcat(joined_str, qstr_str(self->u_str));
758 }
759 strcat(joined_str, s2);
760 }
761 return py_obj_new_str(qstr_from_str_take(joined_str));
762
763bad_arg:
764 nlr_jump(py_obj_new_exception_2(q_TypeError, "?str.join expecting a list of str's", NULL, NULL));
765}
766
Damien2f06c572013-11-03 18:20:56 +0000767py_obj_t rt_str_format(int n_args, const py_obj_t* args) {
768 assert(IS_O(args[0], O_STR));
769 py_obj_base_t *self = args[0];
770
771 const char *str = qstr_str(self->u_str);
772 int arg_i = 1;
773 vstr_t *vstr = vstr_new();
774 for (; *str; str++) {
775 if (*str == '{') {
776 str++;
777 if (*str == '{') {
778 vstr_add_char(vstr, '{');
779 } else if (*str == '}') {
780 if (arg_i >= n_args) {
781 nlr_jump(py_obj_new_exception_2(q_IndexError, "tuple index out of range", NULL, NULL));
782 }
783 py_obj_print_helper(vstr_printf_wrapper, vstr, args[arg_i]);
784 arg_i++;
785 }
786 } else {
787 vstr_add_char(vstr, *str);
788 }
789 }
790
791 return py_obj_new_str(qstr_from_str_take(vstr->buf));
792}
793
Damienc226dca2013-10-16 16:12:52 +0100794py_obj_t rt_list_append(py_obj_t self_in, py_obj_t arg) {
Damien429d7192013-10-04 19:53:11 +0100795 assert(IS_O(self_in, O_LIST));
796 py_obj_base_t *self = self_in;
Damienc226dca2013-10-16 16:12:52 +0100797 if (self->u_tuple_list.len >= self->u_tuple_list.alloc) {
798 self->u_tuple_list.alloc *= 2;
799 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 +0100800 }
Damienc226dca2013-10-16 16:12:52 +0100801 self->u_tuple_list.items[self->u_tuple_list.len++] = arg;
Damienccfc9c52013-11-02 15:10:37 +0000802 return py_const_none; // return None, as per CPython
Damien429d7192013-10-04 19:53:11 +0100803}
804
Damienbd254452013-10-16 20:39:12 +0100805py_obj_t rt_gen_instance_next(py_obj_t self_in) {
806 py_obj_t ret = rt_iternext(self_in);
807 if (ret == py_const_stop_iteration) {
808 nlr_jump(py_obj_new_exception_0(qstr_from_str_static("StopIteration")));
809 } else {
810 return ret;
811 }
812}
813
Damien429d7192013-10-04 19:53:11 +0100814typedef enum {
Damien826005c2013-10-05 23:17:28 +0100815 PY_CODE_NONE,
Damien429d7192013-10-04 19:53:11 +0100816 PY_CODE_BYTE,
Damien826005c2013-10-05 23:17:28 +0100817 PY_CODE_NATIVE,
818 PY_CODE_INLINE_ASM,
Damien429d7192013-10-04 19:53:11 +0100819} py_code_kind_t;
820
821typedef struct _py_code_t {
822 py_code_kind_t kind;
823 int n_args;
Damienbd254452013-10-16 20:39:12 +0100824 int n_locals;
825 int n_stack;
826 bool is_generator;
Damien429d7192013-10-04 19:53:11 +0100827 union {
828 struct {
Damien429d7192013-10-04 19:53:11 +0100829 byte *code;
830 uint len;
831 } u_byte;
Damien826005c2013-10-05 23:17:28 +0100832 struct {
833 py_fun_t fun;
834 } u_native;
835 struct {
Damiene4af64f2013-10-06 12:04:13 +0100836 void *fun;
Damien826005c2013-10-05 23:17:28 +0100837 } u_inline_asm;
Damien429d7192013-10-04 19:53:11 +0100838 };
839} py_code_t;
840
841static int next_unique_code_id;
842static py_code_t *unique_codes;
843
Damien4ebb32f2013-11-02 14:33:10 +0000844py_obj_t fun_str_join;
Damien2f06c572013-11-03 18:20:56 +0000845py_obj_t fun_str_format;
Damien429d7192013-10-04 19:53:11 +0100846py_obj_t fun_list_append;
Damienbd254452013-10-16 20:39:12 +0100847py_obj_t fun_gen_instance_next;
Damien429d7192013-10-04 19:53:11 +0100848
Damien5ac1b2e2013-10-18 19:58:12 +0100849py_obj_t py_builtin___repl_print__(py_obj_t o) {
850 if (o != py_const_none) {
851 py_obj_print(o);
852 printf("\n");
853 }
854 return py_const_none;
855}
856
Damien429d7192013-10-04 19:53:11 +0100857py_obj_t py_builtin_print(py_obj_t o) {
858 if (IS_O(o, O_STR)) {
859 // special case, print string raw
860 printf("%s\n", qstr_str(((py_obj_base_t*)o)->u_str));
861 } else {
862 // print the object Python style
863 py_obj_print(o);
864 printf("\n");
865 }
866 return py_const_none;
867}
868
869py_obj_t py_builtin_len(py_obj_t o_in) {
870 py_small_int_t len = 0;
Damienc226dca2013-10-16 16:12:52 +0100871 if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) {
Damien429d7192013-10-04 19:53:11 +0100872 py_obj_base_t *o = o_in;
Damienc226dca2013-10-16 16:12:52 +0100873 len = o->u_tuple_list.len;
Damien429d7192013-10-04 19:53:11 +0100874 } else if (IS_O(o_in, O_MAP)) {
875 py_obj_base_t *o = o_in;
876 len = o->u_map.used;
877 } else {
878 assert(0);
879 }
880 return TO_SMALL_INT(len);
881}
882
Damien7410e442013-11-02 19:47:57 +0000883py_obj_t py_builtin_abs(py_obj_t o_in) {
884 if (IS_SMALL_INT(o_in)) {
885 py_small_int_t val = FROM_SMALL_INT(o_in);
886 if (val < 0) {
887 val = -val;
888 }
889 return TO_SMALL_INT(val);
890 } else if (IS_O(o_in, O_FLOAT)) {
891 py_obj_base_t *o = o_in;
892 // TODO check for NaN etc
893 if (o->u_float < 0) {
894 return py_obj_new_float(-o->u_float);
895 } else {
896 return o_in;
897 }
898 } else if (IS_O(o_in, O_COMPLEX)) {
899 py_obj_base_t *o = o_in;
900 return py_obj_new_float(sqrt(o->u_complex.real*o->u_complex.real + o->u_complex.imag*o->u_complex.imag));
901 } else {
902 assert(0);
903 return py_const_none;
904 }
905}
906
Damiena3977762013-10-09 23:10:10 +0100907py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name) {
908 // we differ from CPython: we set the new __locals__ object here
Damieneb19efb2013-10-10 22:06:54 +0100909 py_map_t *old_locals = map_locals;
Damiena3977762013-10-09 23:10:10 +0100910 py_map_t *class_locals = py_map_new(MAP_QSTR, 0);
Damieneb19efb2013-10-10 22:06:54 +0100911 map_locals = class_locals;
Damiena3977762013-10-09 23:10:10 +0100912
913 // call the class code
914 rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef);
915
916 // restore old __locals__ object
917 map_locals = old_locals;
918
919 // create and return the new class
Damien429d7192013-10-04 19:53:11 +0100920 py_obj_base_t *o = m_new(py_obj_base_t, 1);
921 o->kind = O_CLASS;
Damiena3977762013-10-09 23:10:10 +0100922 o->u_class.locals = class_locals;
Damien429d7192013-10-04 19:53:11 +0100923 return o;
924}
925
Damience89a212013-10-15 22:25:17 +0100926py_obj_t py_builtin_range(py_obj_t o_arg) {
Damien33af3bf2013-11-03 14:39:47 +0000927 return py_obj_new_range(0, py_obj_get_int(o_arg), 1);
Damience89a212013-10-15 22:25:17 +0100928}
929
Damiena1ddfcc2013-10-10 23:25:50 +0100930#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100931FILE *fp_native = NULL;
Damiena1ddfcc2013-10-10 23:25:50 +0100932#endif
Damien429d7192013-10-04 19:53:11 +0100933
Damien8b3a7c22013-10-23 20:20:17 +0100934void rt_init(void) {
Damien429d7192013-10-04 19:53:11 +0100935 q_append = qstr_from_str_static("append");
Damien4ebb32f2013-11-02 14:33:10 +0000936 q_join = qstr_from_str_static("join");
Damien2f06c572013-11-03 18:20:56 +0000937 q_format = qstr_from_str_static("format");
Damien429d7192013-10-04 19:53:11 +0100938 q___build_class__ = qstr_from_str_static("__build_class__");
Damienbd254452013-10-16 20:39:12 +0100939 q___next__ = qstr_from_str_static("__next__");
Damience89a212013-10-15 22:25:17 +0100940 q_AttributeError = qstr_from_str_static("AttributeError");
Damienc226dca2013-10-16 16:12:52 +0100941 q_IndexError = qstr_from_str_static("IndexError");
Damien5ac1b2e2013-10-18 19:58:12 +0100942 q_KeyError = qstr_from_str_static("KeyError");
Damience89a212013-10-15 22:25:17 +0100943 q_NameError = qstr_from_str_static("NameError");
944 q_TypeError = qstr_from_str_static("TypeError");
Damien7410e442013-11-02 19:47:57 +0000945 q_SyntaxError = qstr_from_str_static("SyntaxError");
Damien429d7192013-10-04 19:53:11 +0100946
947 py_const_none = py_obj_new_const("None");
948 py_const_false = py_obj_new_const("False");
949 py_const_true = py_obj_new_const("True");
Damience89a212013-10-15 22:25:17 +0100950 py_const_stop_iteration = py_obj_new_const("StopIteration");
Damien429d7192013-10-04 19:53:11 +0100951
Damieneb19efb2013-10-10 22:06:54 +0100952 // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
953 map_locals = map_globals = py_map_new(MAP_QSTR, 1);
954 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 +0100955
956 py_map_init(&map_builtins, MAP_QSTR, 3);
Damien5ac1b2e2013-10-18 19:58:12 +0100957 py_qstr_map_lookup(&map_builtins, qstr_from_str_static("__repl_print__"), true)->value = rt_make_function_1(py_builtin___repl_print__);
Damien2f06c572013-11-03 18:20:56 +0000958 py_qstr_map_lookup(&map_builtins, qstr_from_str_static("print"), true)->value = rt_make_function_1(py_builtin_print);
959 py_qstr_map_lookup(&map_builtins, qstr_from_str_static("len"), true)->value = rt_make_function_1(py_builtin_len);
Damien7410e442013-11-02 19:47:57 +0000960 py_qstr_map_lookup(&map_builtins, qstr_from_str_static("abs"), true)->value = rt_make_function_1(py_builtin_abs);
Damien429d7192013-10-04 19:53:11 +0100961 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 +0100962 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 +0100963
Damien5ac1b2e2013-10-18 19:58:12 +0100964 next_unique_code_id = 2; // 1 is reserved for the __main__ module scope
Damien429d7192013-10-04 19:53:11 +0100965 unique_codes = NULL;
966
Damien4ebb32f2013-11-02 14:33:10 +0000967 fun_str_join = rt_make_function_2(rt_str_join);
Damien2f06c572013-11-03 18:20:56 +0000968 fun_str_format = rt_make_function_var(1, rt_str_format);
Damienc226dca2013-10-16 16:12:52 +0100969 fun_list_append = rt_make_function_2(rt_list_append);
Damienbd254452013-10-16 20:39:12 +0100970 fun_gen_instance_next = rt_make_function_1(rt_gen_instance_next);
Damien429d7192013-10-04 19:53:11 +0100971
Damiena1ddfcc2013-10-10 23:25:50 +0100972#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100973 fp_native = fopen("out-native", "wb");
Damiena1ddfcc2013-10-10 23:25:50 +0100974#endif
Damien429d7192013-10-04 19:53:11 +0100975}
976
Damien8b3a7c22013-10-23 20:20:17 +0100977void rt_deinit(void) {
Damiena1ddfcc2013-10-10 23:25:50 +0100978#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100979 if (fp_native != NULL) {
980 fclose(fp_native);
981 }
Damiena1ddfcc2013-10-10 23:25:50 +0100982#endif
Damien429d7192013-10-04 19:53:11 +0100983}
984
Damien5ac1b2e2013-10-18 19:58:12 +0100985int rt_get_unique_code_id(bool is_main_module) {
986 if (is_main_module) {
987 return 1;
988 } else {
989 return next_unique_code_id++;
990 }
Damien429d7192013-10-04 19:53:11 +0100991}
992
Damien8b3a7c22013-10-23 20:20:17 +0100993static void alloc_unique_codes(void) {
Damien429d7192013-10-04 19:53:11 +0100994 if (unique_codes == NULL) {
Damiene0b18642013-11-02 16:41:24 +0000995 unique_codes = m_new(py_code_t, next_unique_code_id + 10); // XXX hack until we fix the REPL allocation problem
Damien826005c2013-10-05 23:17:28 +0100996 for (int i = 0; i < next_unique_code_id; i++) {
997 unique_codes[i].kind = PY_CODE_NONE;
998 }
Damien429d7192013-10-04 19:53:11 +0100999 }
Damien826005c2013-10-05 23:17:28 +01001000}
1001
Damienbd254452013-10-16 20:39:12 +01001002void 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 +01001003 alloc_unique_codes();
1004
1005 assert(unique_code_id < next_unique_code_id);
1006 unique_codes[unique_code_id].kind = PY_CODE_BYTE;
1007 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +01001008 unique_codes[unique_code_id].n_locals = n_locals;
1009 unique_codes[unique_code_id].n_stack = n_stack;
1010 unique_codes[unique_code_id].is_generator = is_generator;
Damien826005c2013-10-05 23:17:28 +01001011 unique_codes[unique_code_id].u_byte.code = code;
1012 unique_codes[unique_code_id].u_byte.len = len;
1013
1014 DEBUG_printf("assign byte code: id=%d code=%p len=%u n_args=%d\n", unique_code_id, code, len, n_args);
1015}
1016
1017void rt_assign_native_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
1018 alloc_unique_codes();
1019
Damienb05d7072013-10-05 13:37:10 +01001020 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
Damien429d7192013-10-04 19:53:11 +01001021 unique_codes[unique_code_id].kind = PY_CODE_NATIVE;
1022 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +01001023 unique_codes[unique_code_id].n_locals = 0;
1024 unique_codes[unique_code_id].n_stack = 0;
1025 unique_codes[unique_code_id].is_generator = false;
Damien429d7192013-10-04 19:53:11 +01001026 unique_codes[unique_code_id].u_native.fun = fun;
1027
Damiena1ddfcc2013-10-10 23:25:50 +01001028#ifdef DEBUG_PRINT
Damien429d7192013-10-04 19:53:11 +01001029 DEBUG_printf("assign native code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
1030 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
1031 for (int i = 0; i < 128 && i < len; i++) {
1032 if (i > 0 && i % 16 == 0) {
1033 DEBUG_printf("\n");
1034 }
1035 DEBUG_printf(" %02x", fun_data[i]);
1036 }
1037 DEBUG_printf("\n");
1038
Damiena1ddfcc2013-10-10 23:25:50 +01001039#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +01001040 if (fp_native != NULL) {
1041 fwrite(fun_data, len, 1, fp_native);
Damien13ed3a62013-10-08 09:05:10 +01001042 fflush(fp_native);
Damien429d7192013-10-04 19:53:11 +01001043 }
Damiena1ddfcc2013-10-10 23:25:50 +01001044#endif
1045#endif
Damien429d7192013-10-04 19:53:11 +01001046}
1047
Damien826005c2013-10-05 23:17:28 +01001048void rt_assign_inline_asm_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
1049 alloc_unique_codes();
Damien429d7192013-10-04 19:53:11 +01001050
Damien826005c2013-10-05 23:17:28 +01001051 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
1052 unique_codes[unique_code_id].kind = PY_CODE_INLINE_ASM;
1053 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +01001054 unique_codes[unique_code_id].n_locals = 0;
1055 unique_codes[unique_code_id].n_stack = 0;
1056 unique_codes[unique_code_id].is_generator = false;
Damien826005c2013-10-05 23:17:28 +01001057 unique_codes[unique_code_id].u_inline_asm.fun = fun;
1058
Damiena1ddfcc2013-10-10 23:25:50 +01001059#ifdef DEBUG_PRINT
Damien826005c2013-10-05 23:17:28 +01001060 DEBUG_printf("assign inline asm code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
1061 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
1062 for (int i = 0; i < 128 && i < len; i++) {
1063 if (i > 0 && i % 16 == 0) {
1064 DEBUG_printf("\n");
1065 }
1066 DEBUG_printf(" %02x", fun_data[i]);
1067 }
1068 DEBUG_printf("\n");
1069
Damiena1ddfcc2013-10-10 23:25:50 +01001070#ifdef WRITE_NATIVE
Damien826005c2013-10-05 23:17:28 +01001071 if (fp_native != NULL) {
1072 fwrite(fun_data, len, 1, fp_native);
1073 }
Damiena1ddfcc2013-10-10 23:25:50 +01001074#endif
1075#endif
Damien429d7192013-10-04 19:53:11 +01001076}
1077
Damiena3977762013-10-09 23:10:10 +01001078bool py_obj_is_callable(py_obj_t o_in) {
1079 if (IS_SMALL_INT(o_in)) {
1080 return false;
1081 } else {
1082 py_obj_base_t *o = o_in;
1083 switch (o->kind) {
1084 case O_FUN_0:
1085 case O_FUN_1:
1086 case O_FUN_2:
Damien2f06c572013-11-03 18:20:56 +00001087 case O_FUN_VAR:
Damiena3977762013-10-09 23:10:10 +01001088 case O_FUN_N:
1089 case O_FUN_BC:
1090 case O_FUN_ASM:
Damieneb19efb2013-10-10 22:06:54 +01001091 // what about O_CLASS, and an O_OBJ that has a __call__ method?
Damiena3977762013-10-09 23:10:10 +01001092 return true;
1093 default:
1094 return false;
1095 }
1096 }
1097}
1098
Damien429d7192013-10-04 19:53:11 +01001099void py_obj_print(py_obj_t o_in) {
Damien2f06c572013-11-03 18:20:56 +00001100 py_obj_print_helper(printf_wrapper, NULL, o_in);
Damien429d7192013-10-04 19:53:11 +01001101}
1102
Damien7410e442013-11-02 19:47:57 +00001103#define PARSE_DEC_IN_INTG (1)
1104#define PARSE_DEC_IN_FRAC (2)
1105#define PARSE_DEC_IN_EXP (3)
1106
1107py_obj_t rt_load_const_dec(qstr qstr) {
1108#if MICROPY_ENABLE_FLOAT
1109 DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
1110 const char *s = qstr_str(qstr);
1111 int in = PARSE_DEC_IN_INTG;
1112 py_float_t dec_val = 0;
1113 bool exp_neg = false;
1114 int exp_val = 0;
1115 int exp_extra = 0;
1116 bool imag = false;
1117 for (; *s; s++) {
1118 int dig = *s;
1119 if ('0' <= dig && dig <= '9') {
1120 dig -= '0';
1121 if (in == PARSE_DEC_IN_EXP) {
1122 exp_val = 10 * exp_val + dig;
1123 } else {
1124 dec_val = 10 * dec_val + dig;
1125 if (in == PARSE_DEC_IN_FRAC) {
1126 exp_extra -= 1;
1127 }
1128 }
1129 } else if (in == PARSE_DEC_IN_INTG && dig == '.') {
1130 in = PARSE_DEC_IN_FRAC;
1131 } else if (in != PARSE_DEC_IN_EXP && (dig == 'E' || dig == 'e')) {
1132 in = PARSE_DEC_IN_EXP;
1133 if (s[1] == '+') {
1134 s++;
1135 } else if (s[1] == '-') {
1136 s++;
1137 exp_neg = true;
1138 }
1139 } else if (dig == 'J' || dig == 'j') {
1140 s++;
1141 imag = true;
1142 break;
1143 } else {
1144 // unknown character
1145 break;
1146 }
1147 }
1148 if (*s != 0) {
1149 nlr_jump(py_obj_new_exception_2(q_SyntaxError, "invalid syntax for number", NULL, NULL));
1150 }
1151 if (exp_neg) {
1152 exp_val = -exp_val;
1153 }
1154 exp_val += exp_extra;
1155 for (; exp_val > 0; exp_val--) {
1156 dec_val *= 10;
1157 }
1158 for (; exp_val < 0; exp_val++) {
1159 dec_val *= 0.1;
1160 }
1161 if (imag) {
1162 return py_obj_new_complex(0, dec_val);
1163 } else {
1164 return py_obj_new_float(dec_val);
1165 }
1166#else
1167 nlr_jump(py_obj_new_exception_2(q_SyntaxError, "decimal numbers not supported", NULL, NULL));
1168#endif
1169}
1170
Damien429d7192013-10-04 19:53:11 +01001171py_obj_t rt_load_const_str(qstr qstr) {
1172 DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
1173 return py_obj_new_str(qstr);
1174}
1175
1176py_obj_t rt_load_name(qstr qstr) {
1177 // logic: search locals, globals, builtins
Damiena3977762013-10-09 23:10:10 +01001178 DEBUG_OP_printf("load name %s\n", qstr_str(qstr));
Damieneb19efb2013-10-10 22:06:54 +01001179 py_map_elem_t *elem = py_qstr_map_lookup(map_locals, qstr, false);
Damiena3977762013-10-09 23:10:10 +01001180 if (elem == NULL) {
Damieneb19efb2013-10-10 22:06:54 +01001181 elem = py_qstr_map_lookup(map_globals, qstr, false);
Damiena3977762013-10-09 23:10:10 +01001182 if (elem == NULL) {
1183 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
1184 if (elem == NULL) {
Damience89a212013-10-15 22:25:17 +01001185 nlr_jump(py_obj_new_exception_2(q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL));
Damiena3977762013-10-09 23:10:10 +01001186 }
1187 }
1188 }
1189 return elem->value;
1190}
1191
1192py_obj_t rt_load_global(qstr qstr) {
1193 // logic: search globals, builtins
1194 DEBUG_OP_printf("load global %s\n", qstr_str(qstr));
Damieneb19efb2013-10-10 22:06:54 +01001195 py_map_elem_t *elem = py_qstr_map_lookup(map_globals, qstr, false);
Damien429d7192013-10-04 19:53:11 +01001196 if (elem == NULL) {
1197 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
1198 if (elem == NULL) {
Damience89a212013-10-15 22:25:17 +01001199 nlr_jump(py_obj_new_exception_2(q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL));
Damien429d7192013-10-04 19:53:11 +01001200 }
1201 }
1202 return elem->value;
1203}
1204
Damien8b3a7c22013-10-23 20:20:17 +01001205py_obj_t rt_load_build_class(void) {
Damien429d7192013-10-04 19:53:11 +01001206 DEBUG_OP_printf("load_build_class\n");
1207 py_map_elem_t *elem = py_qstr_map_lookup(&map_builtins, q___build_class__, false);
1208 if (elem == NULL) {
1209 printf("name doesn't exist: __build_class__\n");
1210 assert(0);
1211 }
1212 return elem->value;
1213}
1214
1215void rt_store_name(qstr qstr, py_obj_t obj) {
Damiena3977762013-10-09 23:10:10 +01001216 DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qstr), obj);
Damieneb19efb2013-10-10 22:06:54 +01001217 py_qstr_map_lookup(map_locals, qstr, true)->value = obj;
Damiena3977762013-10-09 23:10:10 +01001218}
1219
1220void rt_store_global(qstr qstr, py_obj_t obj) {
1221 DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qstr), obj);
Damieneb19efb2013-10-10 22:06:54 +01001222 py_qstr_map_lookup(map_globals, qstr, true)->value = obj;
Damien429d7192013-10-04 19:53:11 +01001223}
1224
1225py_obj_t rt_unary_op(int op, py_obj_t arg) {
Damien7410e442013-11-02 19:47:57 +00001226 DEBUG_OP_printf("unary %d %p\n", op, arg);
1227 if (IS_SMALL_INT(arg)) {
1228 py_small_int_t val = FROM_SMALL_INT(arg);
1229 switch (op) {
1230 case RT_UNARY_OP_NOT: if (val != 0) { return py_const_true;} else { return py_const_false; }
1231 case RT_UNARY_OP_POSITIVE: break;
1232 case RT_UNARY_OP_NEGATIVE: val = -val; break;
1233 case RT_UNARY_OP_INVERT: val = ~val; break;
1234 default: assert(0); val = 0;
1235 }
1236 if (fit_small_int(val)) {
1237 return TO_SMALL_INT(val);
1238 }
1239#if MICROPY_ENABLE_FLOAT
1240 } else if (IS_O(arg, O_FLOAT)) {
1241 py_float_t val = py_obj_get_float(arg);
1242 switch (op) {
1243 case RT_UNARY_OP_NOT: if (val != 0) { return py_const_true;} else { return py_const_false; }
1244 case RT_UNARY_OP_POSITIVE: break;
1245 case RT_UNARY_OP_NEGATIVE: val = -val; break;
1246 case RT_UNARY_OP_INVERT: nlr_jump(py_obj_new_exception_2(q_TypeError, "bad operand type for unary ~: 'float'", NULL, NULL));
1247 default: assert(0); val = 0;
1248 }
1249 return py_obj_new_float(val);
1250#endif
1251 }
Damien429d7192013-10-04 19:53:11 +01001252 assert(0);
1253 return py_const_none;
1254}
1255
Damienc226dca2013-10-16 16:12:52 +01001256uint get_index(py_obj_base_t *base, py_obj_t index) {
1257 // assumes base is O_TUPLE or O_LIST
1258 // TODO False and True are considered 0 and 1 for indexing purposes
1259 int len = base->u_tuple_list.len;
1260 if (IS_SMALL_INT(index)) {
1261 int i = FROM_SMALL_INT(index);
1262 if (i < 0) {
1263 i += len;
1264 }
1265 if (i < 0 || i >= len) {
1266 nlr_jump(py_obj_new_exception_2(q_IndexError, "%s index out of range", py_obj_get_type_str(base), NULL));
1267 }
1268 return i;
1269 } else {
1270 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)));
1271 }
1272}
1273
Damien429d7192013-10-04 19:53:11 +01001274py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs) {
1275 DEBUG_OP_printf("binary %d %p %p\n", op, lhs, rhs);
1276 if (op == RT_BINARY_OP_SUBSCR) {
Damienc226dca2013-10-16 16:12:52 +01001277 if ((IS_O(lhs, O_TUPLE) || IS_O(lhs, O_LIST))) {
Damien5ac1b2e2013-10-18 19:58:12 +01001278 // tuple/list load
Damienc226dca2013-10-16 16:12:52 +01001279 uint index = get_index(lhs, rhs);
1280 return ((py_obj_base_t*)lhs)->u_tuple_list.items[index];
Damien5ac1b2e2013-10-18 19:58:12 +01001281 } else if (IS_O(lhs, O_MAP)) {
1282 // map load
1283 py_map_elem_t *elem = py_map_lookup(lhs, rhs, false);
1284 if (elem == NULL) {
1285 nlr_jump(py_obj_new_exception_2(q_KeyError, "<value>", NULL, NULL));
1286 } else {
1287 return elem->value;
1288 }
Damien429d7192013-10-04 19:53:11 +01001289 } else {
1290 assert(0);
1291 }
1292 } else if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
Damien4ebb32f2013-11-02 14:33:10 +00001293 py_small_int_t lhs_val = FROM_SMALL_INT(lhs);
1294 py_small_int_t rhs_val = FROM_SMALL_INT(rhs);
Damien429d7192013-10-04 19:53:11 +01001295 switch (op) {
Damien7b2d3f32013-10-22 16:53:02 +01001296 case RT_BINARY_OP_OR:
Damien7410e442013-11-02 19:47:57 +00001297 case RT_BINARY_OP_INPLACE_OR: lhs_val |= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001298 case RT_BINARY_OP_XOR:
Damien7410e442013-11-02 19:47:57 +00001299 case RT_BINARY_OP_INPLACE_XOR: lhs_val ^= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001300 case RT_BINARY_OP_AND:
Damien7410e442013-11-02 19:47:57 +00001301 case RT_BINARY_OP_INPLACE_AND: lhs_val &= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001302 case RT_BINARY_OP_LSHIFT:
Damien7410e442013-11-02 19:47:57 +00001303 case RT_BINARY_OP_INPLACE_LSHIFT: lhs_val <<= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001304 case RT_BINARY_OP_RSHIFT:
Damien7410e442013-11-02 19:47:57 +00001305 case RT_BINARY_OP_INPLACE_RSHIFT: lhs_val >>= rhs_val; break;
Damien429d7192013-10-04 19:53:11 +01001306 case RT_BINARY_OP_ADD:
Damien7410e442013-11-02 19:47:57 +00001307 case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
Damienbd254452013-10-16 20:39:12 +01001308 case RT_BINARY_OP_SUBTRACT:
Damien7410e442013-11-02 19:47:57 +00001309 case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001310 case RT_BINARY_OP_MULTIPLY:
Damien7410e442013-11-02 19:47:57 +00001311 case RT_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001312 case RT_BINARY_OP_FLOOR_DIVIDE:
Damien7410e442013-11-02 19:47:57 +00001313 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: lhs_val /= rhs_val; break;
Damien3ef4abb2013-10-12 16:53:13 +01001314#if MICROPY_ENABLE_FLOAT
Damien7b2d3f32013-10-22 16:53:02 +01001315 case RT_BINARY_OP_TRUE_DIVIDE:
Damien7410e442013-11-02 19:47:57 +00001316 case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: return py_obj_new_float((py_float_t)lhs_val / (py_float_t)rhs_val);
Damien429d7192013-10-04 19:53:11 +01001317#endif
Damien4ebb32f2013-11-02 14:33:10 +00001318 case RT_BINARY_OP_POWER:
1319 case RT_BINARY_OP_INPLACE_POWER:
1320 // TODO
1321 if (rhs_val == 2) {
Damien7410e442013-11-02 19:47:57 +00001322 lhs_val = lhs_val * lhs_val;
Damien4ebb32f2013-11-02 14:33:10 +00001323 break;
1324 }
Damien7410e442013-11-02 19:47:57 +00001325 default: printf("%d\n", op); assert(0);
Damien429d7192013-10-04 19:53:11 +01001326 }
Damien7410e442013-11-02 19:47:57 +00001327 if (fit_small_int(lhs_val)) {
1328 return TO_SMALL_INT(lhs_val);
Damien429d7192013-10-04 19:53:11 +01001329 }
Damien4ebb32f2013-11-02 14:33:10 +00001330#if MICROPY_ENABLE_FLOAT
Damien7410e442013-11-02 19:47:57 +00001331 } else if (IS_O(lhs, O_COMPLEX) || IS_O(rhs, O_COMPLEX)) {
1332 py_float_t lhs_real, lhs_imag, rhs_real, rhs_imag;
1333 py_obj_get_complex(lhs, &lhs_real, &lhs_imag);
1334 py_obj_get_complex(rhs, &rhs_real, &rhs_imag);
Damien4ebb32f2013-11-02 14:33:10 +00001335 switch (op) {
1336 case RT_BINARY_OP_ADD:
Damien7410e442013-11-02 19:47:57 +00001337 case RT_BINARY_OP_INPLACE_ADD:
1338 lhs_real += rhs_real;
1339 lhs_imag += rhs_imag;
1340 break;
Damien4ebb32f2013-11-02 14:33:10 +00001341 case RT_BINARY_OP_SUBTRACT:
Damien7410e442013-11-02 19:47:57 +00001342 case RT_BINARY_OP_INPLACE_SUBTRACT:
1343 lhs_real -= rhs_real;
1344 lhs_imag -= rhs_imag;
1345 break;
Damien4ebb32f2013-11-02 14:33:10 +00001346 case RT_BINARY_OP_MULTIPLY:
Damien7410e442013-11-02 19:47:57 +00001347 case RT_BINARY_OP_INPLACE_MULTIPLY:
1348 {
1349 py_float_t real = lhs_real * rhs_real - lhs_imag * rhs_imag;
1350 lhs_imag = lhs_real * rhs_imag + lhs_imag * rhs_real;
1351 lhs_real = real;
1352 break;
1353 }
1354 /* TODO floor(?) the value
1355 case RT_BINARY_OP_FLOOR_DIVIDE:
1356 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break;
1357 */
1358 /* TODO
1359 case RT_BINARY_OP_TRUE_DIVIDE:
1360 case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: val = lhs_val / rhs_val; break;
1361 */
1362 default: printf("%d\n", op); assert(0);
1363 }
1364 return py_obj_new_complex(lhs_real, lhs_imag);
1365 } else if (IS_O(lhs, O_FLOAT) || IS_O(rhs, O_FLOAT)) {
1366 py_float_t lhs_val = py_obj_get_float(lhs);
1367 py_float_t rhs_val = py_obj_get_float(rhs);
1368 switch (op) {
1369 case RT_BINARY_OP_ADD:
1370 case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
1371 case RT_BINARY_OP_SUBTRACT:
1372 case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
1373 case RT_BINARY_OP_MULTIPLY:
1374 case RT_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;
Damien4ebb32f2013-11-02 14:33:10 +00001375 /* TODO floor(?) the value
1376 case RT_BINARY_OP_FLOOR_DIVIDE:
1377 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break;
1378 */
1379 case RT_BINARY_OP_TRUE_DIVIDE:
Damien7410e442013-11-02 19:47:57 +00001380 case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: lhs_val /= rhs_val; break;
1381 default: printf("%d\n", op); assert(0);
Damien4ebb32f2013-11-02 14:33:10 +00001382 }
Damien7410e442013-11-02 19:47:57 +00001383 return py_obj_new_float(lhs_val);
Damien4ebb32f2013-11-02 14:33:10 +00001384#endif
Damien429d7192013-10-04 19:53:11 +01001385 } else if (IS_O(lhs, O_STR) && IS_O(rhs, O_STR)) {
1386 const char *lhs_str = qstr_str(((py_obj_base_t*)lhs)->u_str);
1387 const char *rhs_str = qstr_str(((py_obj_base_t*)rhs)->u_str);
1388 char *val;
1389 switch (op) {
1390 case RT_BINARY_OP_ADD:
1391 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;
1392 default: printf("%d\n", op); assert(0); val = NULL;
1393 }
1394 return py_obj_new_str(qstr_from_str_take(val));
1395 }
1396 assert(0);
1397 return py_const_none;
1398}
1399
1400py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs) {
1401 DEBUG_OP_printf("compare %d %p %p\n", op, lhs, rhs);
Damien7b2d3f32013-10-22 16:53:02 +01001402
1403 // deal with == and !=
1404 if (op == RT_COMPARE_OP_EQUAL || op == RT_COMPARE_OP_NOT_EQUAL) {
1405 if (py_obj_equal(lhs, rhs)) {
1406 if (op == RT_COMPARE_OP_EQUAL) {
1407 return py_const_true;
1408 } else {
1409 return py_const_false;
1410 }
1411 } else {
1412 if (op == RT_COMPARE_OP_EQUAL) {
1413 return py_const_false;
1414 } else {
1415 return py_const_true;
1416 }
1417 }
1418 }
1419
1420 // deal with small ints
Damien429d7192013-10-04 19:53:11 +01001421 if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
Damien4ebb32f2013-11-02 14:33:10 +00001422 py_small_int_t lhs_val = FROM_SMALL_INT(lhs);
1423 py_small_int_t rhs_val = FROM_SMALL_INT(rhs);
Damien429d7192013-10-04 19:53:11 +01001424 int cmp;
1425 switch (op) {
Damien4ebb32f2013-11-02 14:33:10 +00001426 case RT_COMPARE_OP_LESS: cmp = lhs_val < rhs_val; break;
1427 case RT_COMPARE_OP_MORE: cmp = lhs_val > rhs_val; break;
1428 case RT_COMPARE_OP_LESS_EQUAL: cmp = lhs_val <= rhs_val; break;
1429 case RT_COMPARE_OP_MORE_EQUAL: cmp = lhs_val >= rhs_val; break;
Damien429d7192013-10-04 19:53:11 +01001430 default: assert(0); cmp = 0;
1431 }
1432 if (cmp) {
1433 return py_const_true;
1434 } else {
1435 return py_const_false;
1436 }
1437 }
Damien7b2d3f32013-10-22 16:53:02 +01001438
Damien4ebb32f2013-11-02 14:33:10 +00001439#if MICROPY_ENABLE_FLOAT
1440 // deal with floats
1441 if (IS_O(lhs, O_FLOAT) || IS_O(rhs, O_FLOAT)) {
Damien7410e442013-11-02 19:47:57 +00001442 py_float_t lhs_val = py_obj_get_float(lhs);
1443 py_float_t rhs_val = py_obj_get_float(rhs);
Damien4ebb32f2013-11-02 14:33:10 +00001444 int cmp;
1445 switch (op) {
1446 case RT_COMPARE_OP_LESS: cmp = lhs_val < rhs_val; break;
1447 case RT_COMPARE_OP_MORE: cmp = lhs_val > rhs_val; break;
1448 case RT_COMPARE_OP_LESS_EQUAL: cmp = lhs_val <= rhs_val; break;
1449 case RT_COMPARE_OP_MORE_EQUAL: cmp = lhs_val >= rhs_val; break;
1450 default: assert(0); cmp = 0;
1451 }
1452 if (cmp) {
1453 return py_const_true;
1454 } else {
1455 return py_const_false;
1456 }
1457 }
1458#endif
1459
Damien7b2d3f32013-10-22 16:53:02 +01001460 // not implemented
Damien429d7192013-10-04 19:53:11 +01001461 assert(0);
1462 return py_const_none;
1463}
1464
1465py_obj_t rt_make_function_from_id(int unique_code_id) {
Damienb05d7072013-10-05 13:37:10 +01001466 DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id);
1467 if (unique_code_id < 1 || unique_code_id >= next_unique_code_id) {
Damien429d7192013-10-04 19:53:11 +01001468 // illegal code id
1469 return py_const_none;
1470 }
1471 py_code_t *c = &unique_codes[unique_code_id];
1472 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1473 switch (c->kind) {
Damien826005c2013-10-05 23:17:28 +01001474 case PY_CODE_BYTE:
1475 o->kind = O_FUN_BC;
1476 o->u_fun_bc.n_args = c->n_args;
1477 o->u_fun_bc.code = c->u_byte.code;
1478 o->u_fun_bc.len = c->u_byte.len;
1479 break;
Damien429d7192013-10-04 19:53:11 +01001480 case PY_CODE_NATIVE:
1481 switch (c->n_args) {
1482 case 0: o->kind = O_FUN_0; break;
1483 case 1: o->kind = O_FUN_1; break;
1484 case 2: o->kind = O_FUN_2; break;
1485 default: assert(0);
1486 }
1487 o->u_fun.fun = c->u_native.fun;
1488 break;
Damien826005c2013-10-05 23:17:28 +01001489 case PY_CODE_INLINE_ASM:
1490 o->kind = O_FUN_ASM;
1491 o->u_fun_asm.n_args = c->n_args;
1492 o->u_fun_asm.fun = c->u_inline_asm.fun;
Damien429d7192013-10-04 19:53:11 +01001493 break;
1494 default:
1495 assert(0);
1496 }
Damienbd254452013-10-16 20:39:12 +01001497
1498 // check for generator functions and if so wrap in generator object
1499 if (c->is_generator) {
1500 py_obj_base_t *o2 = m_new(py_obj_base_t, 1);
1501 o2->kind = O_GEN_WRAP;
1502 // we have at least 3 locals so the bc can write back fast[0,1,2] safely; should improve how this is done
1503 o2->u_gen_wrap.n_state = (c->n_locals < 3 ? 3 : c->n_locals) + c->n_stack;
1504 o2->u_gen_wrap.fun = o;
1505 o = o2;
1506 }
1507
Damien429d7192013-10-04 19:53:11 +01001508 return o;
1509}
1510
1511py_obj_t rt_make_function_0(py_fun_0_t fun) {
1512 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1513 o->kind = O_FUN_0;
1514 o->u_fun.fun = fun;
1515 return o;
1516}
1517
1518py_obj_t rt_make_function_1(py_fun_1_t fun) {
1519 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1520 o->kind = O_FUN_1;
1521 o->u_fun.fun = fun;
1522 return o;
1523}
1524
1525py_obj_t rt_make_function_2(py_fun_2_t fun) {
1526 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1527 o->kind = O_FUN_2;
1528 o->u_fun.fun = fun;
1529 return o;
1530}
1531
1532py_obj_t rt_make_function(int n_args, py_fun_t code) {
1533 // assumes code is a pointer to a py_fun_t (i think this is safe...)
1534 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1535 o->kind = O_FUN_N;
Damien429d7192013-10-04 19:53:11 +01001536 o->u_fun.n_args = n_args;
Damien826005c2013-10-05 23:17:28 +01001537 o->u_fun.fun = code;
Damien429d7192013-10-04 19:53:11 +01001538 return o;
1539}
1540
Damien2f06c572013-11-03 18:20:56 +00001541py_obj_t rt_make_function_var(int n_fixed_args, py_fun_var_t f) {
1542 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1543 o->kind = O_FUN_VAR;
1544 o->u_fun.n_args = n_fixed_args;
1545 o->u_fun.fun = f;
1546 return o;
1547}
1548
Damieneb19efb2013-10-10 22:06:54 +01001549py_obj_t rt_call_function_0(py_obj_t fun) {
1550 return rt_call_function_n(fun, 0, NULL);
1551}
1552
1553py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) {
1554 return rt_call_function_n(fun, 1, &arg);
1555}
1556
1557py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) {
1558 py_obj_t args[2];
1559 args[1] = arg1;
1560 args[0] = arg2;
1561 return rt_call_function_n(fun, 2, args);
1562}
1563
1564typedef machine_uint_t (*inline_asm_fun_0_t)();
1565typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t);
1566typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t);
1567typedef machine_uint_t (*inline_asm_fun_3_t)(machine_uint_t, machine_uint_t, machine_uint_t);
1568
Damiene4af64f2013-10-06 12:04:13 +01001569// convert a Python object to a sensible value for inline asm
1570machine_uint_t rt_convert_obj_for_inline_asm(py_obj_t obj) {
1571 // TODO for byte_array, pass pointer to the array
1572 if (IS_SMALL_INT(obj)) {
1573 return FROM_SMALL_INT(obj);
1574 } else if (obj == py_const_none) {
1575 return 0;
1576 } else if (obj == py_const_false) {
1577 return 0;
1578 } else if (obj == py_const_true) {
1579 return 1;
1580 } else {
1581 py_obj_base_t *o = obj;
1582 switch (o->kind) {
1583 case O_STR:
1584 // pointer to the string (it's probably constant though!)
1585 return (machine_uint_t)qstr_str(o->u_str);
1586
Damien3ef4abb2013-10-12 16:53:13 +01001587#if MICROPY_ENABLE_FLOAT
Damiene4af64f2013-10-06 12:04:13 +01001588 case O_FLOAT:
1589 // convert float to int (could also pass in float registers)
Damien7410e442013-11-02 19:47:57 +00001590 return (machine_int_t)o->u_float;
Damienc025ebb2013-10-12 14:30:21 +01001591#endif
Damiene4af64f2013-10-06 12:04:13 +01001592
Damienc226dca2013-10-16 16:12:52 +01001593 case O_TUPLE:
Damiene4af64f2013-10-06 12:04:13 +01001594 case O_LIST:
Damienc226dca2013-10-16 16:12:52 +01001595 // pointer to start of tuple/list (could pass length, but then could use len(x) for that)
1596 return (machine_uint_t)o->u_tuple_list.items;
Damiene4af64f2013-10-06 12:04:13 +01001597
1598 default:
1599 // just pass along a pointer to the object
1600 return (machine_uint_t)obj;
1601 }
1602 }
1603}
1604
1605// convert a return value from inline asm to a sensible Python object
1606py_obj_t rt_convert_val_from_inline_asm(machine_uint_t val) {
1607 return TO_SMALL_INT(val);
1608}
1609
Damieneb19efb2013-10-10 22:06:54 +01001610// args are in reverse order in the array
1611py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args) {
1612 int n_args_fun = 0;
Damien429d7192013-10-04 19:53:11 +01001613 if (IS_O(fun, O_FUN_0)) {
1614 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001615 if (n_args != 0) {
1616 n_args_fun = 0;
1617 goto bad_n_args;
1618 }
1619 DEBUG_OP_printf("calling native %p()\n", o->u_fun.fun);
Damien429d7192013-10-04 19:53:11 +01001620 return ((py_fun_0_t)o->u_fun.fun)();
Damieneb19efb2013-10-10 22:06:54 +01001621
1622 } else if (IS_O(fun, O_FUN_1)) {
1623 py_obj_base_t *o = fun;
1624 if (n_args != 1) {
1625 n_args_fun = 1;
1626 goto bad_n_args;
1627 }
1628 DEBUG_OP_printf("calling native %p(%p)\n", o->u_fun.fun, args[0]);
1629 return ((py_fun_1_t)o->u_fun.fun)(args[0]);
1630
1631 } else if (IS_O(fun, O_FUN_2)) {
1632 py_obj_base_t *o = fun;
1633 if (n_args != 2) {
1634 n_args_fun = 2;
1635 goto bad_n_args;
1636 }
1637 DEBUG_OP_printf("calling native %p(%p, %p)\n", o->u_fun.fun, args[1], args[0]);
1638 return ((py_fun_2_t)o->u_fun.fun)(args[1], args[0]);
1639
1640 // TODO O_FUN_N
1641
Damien2f06c572013-11-03 18:20:56 +00001642 } else if (IS_O(fun, O_FUN_VAR)) {
1643 py_obj_base_t *o = fun;
1644 if (n_args < o->u_fun.n_args) {
1645 nlr_jump(py_obj_new_exception_2(q_TypeError, "<fun name>() missing %d required positional arguments: <list of names of params>", (const char*)(machine_int_t)(o->u_fun.n_args - n_args), NULL));
1646 }
1647 // really the args need to be passed in as a Python tuple, as the form f(*[1,2]) can be used to pass var args
1648 py_obj_t *args_ordered = m_new(py_obj_t, o->u_fun.n_args);
1649 for (int i = 0; i < n_args; i++) {
1650 args_ordered[i] = args[n_args - i - 1];
1651 }
1652 py_obj_t res = ((py_fun_var_t)o->u_fun.fun)(n_args, args_ordered);
1653 m_free(args_ordered);
1654 return res;
1655
Damien429d7192013-10-04 19:53:11 +01001656 } else if (IS_O(fun, O_FUN_BC)) {
1657 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001658 if (n_args != o->u_fun_bc.n_args) {
1659 n_args_fun = o->u_fun_bc.n_args;
1660 goto bad_n_args;
1661 }
1662 DEBUG_OP_printf("calling byte code %p(n_args=%d)\n", o->u_fun_bc.code, n_args);
Damienbd254452013-10-16 20:39:12 +01001663 return py_execute_byte_code(o->u_fun_bc.code, args, n_args);
Damieneb19efb2013-10-10 22:06:54 +01001664
Damiene4af64f2013-10-06 12:04:13 +01001665 } else if (IS_O(fun, O_FUN_ASM)) {
1666 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001667 if (n_args != o->u_fun_asm.n_args) {
1668 n_args_fun = o->u_fun_asm.n_args;
1669 goto bad_n_args;
1670 }
1671 DEBUG_OP_printf("calling inline asm %p(n_args=%d)\n", o->u_fun_asm.fun, n_args);
1672 machine_uint_t ret;
1673 if (n_args == 0) {
1674 ret = ((inline_asm_fun_0_t)o->u_fun_asm.fun)();
1675 } else if (n_args == 1) {
1676 ret = ((inline_asm_fun_1_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[0]));
1677 } else if (n_args == 2) {
1678 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]));
1679 } else if (n_args == 3) {
1680 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]));
1681 } else {
1682 assert(0);
1683 ret = 0;
1684 }
1685 return rt_convert_val_from_inline_asm(ret);
1686
Damienbd254452013-10-16 20:39:12 +01001687 } else if (IS_O(fun, O_GEN_WRAP)) {
1688 py_obj_base_t *o = fun;
1689 py_obj_base_t *o_fun = o->u_gen_wrap.fun;
1690 assert(o_fun->kind == O_FUN_BC); // TODO
1691 if (n_args != o_fun->u_fun_bc.n_args) {
1692 n_args_fun = o_fun->u_fun_bc.n_args;
1693 goto bad_n_args;
1694 }
1695 py_obj_t *state = m_new(py_obj_t, 1 + o->u_gen_wrap.n_state);
1696 // put function object at first slot in state (to keep u_gen_instance small)
1697 state[0] = o_fun;
1698 // init args
1699 for (int i = 0; i < n_args; i++) {
1700 state[1 + i] = args[n_args - 1 - i];
1701 }
1702 py_obj_base_t *o2 = m_new(py_obj_base_t, 1);
1703 o2->kind = O_GEN_INSTANCE;
1704 o2->u_gen_instance.state = state;
1705 o2->u_gen_instance.ip = o_fun->u_fun_bc.code;
1706 o2->u_gen_instance.sp = state + o->u_gen_wrap.n_state;
1707 return o2;
1708
Damiena3977762013-10-09 23:10:10 +01001709 } else if (IS_O(fun, O_BOUND_METH)) {
1710 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001711 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);
1712 if (n_args == 0) {
1713 return rt_call_function_n(o->u_bound_meth.meth, 1, &o->u_bound_meth.self);
1714 } else if (n_args == 1) {
1715 py_obj_t args2[2];
1716 args2[1] = o->u_bound_meth.self;
1717 args2[0] = args[0];
1718 return rt_call_function_n(o->u_bound_meth.meth, 2, args2);
1719 } else {
1720 // TODO not implemented
1721 assert(0);
1722 return py_const_none;
1723 //return rt_call_function_2(o->u_bound_meth.meth, n_args + 1, o->u_bound_meth.self + args);
1724 }
1725
Damiena3977762013-10-09 23:10:10 +01001726 } else if (IS_O(fun, O_CLASS)) {
1727 // instantiate an instance of a class
Damieneb19efb2013-10-10 22:06:54 +01001728 if (n_args != 0) {
1729 n_args_fun = 0;
1730 goto bad_n_args;
1731 }
Damiena3977762013-10-09 23:10:10 +01001732 DEBUG_OP_printf("instantiate object of class %p with no args\n", fun);
1733 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1734 o->kind = O_OBJ;
1735 o->u_obj.class = fun;
1736 o->u_obj.members = py_map_new(MAP_QSTR, 0);
1737 return o;
Damieneb19efb2013-10-10 22:06:54 +01001738
Damien429d7192013-10-04 19:53:11 +01001739 } else {
Damieneb19efb2013-10-10 22:06:54 +01001740 printf("fun %p %d\n", fun, ((py_obj_base_t*)fun)->kind);
Damien429d7192013-10-04 19:53:11 +01001741 assert(0);
1742 return py_const_none;
1743 }
Damien429d7192013-10-04 19:53:11 +01001744
Damieneb19efb2013-10-10 22:06:54 +01001745bad_n_args:
Damienbd254452013-10-16 20:39:12 +01001746 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 +01001747}
1748
Damiena3977762013-10-09 23:10:10 +01001749// args contains: arg(n_args-1) arg(n_args-2) ... arg(0) self/NULL fun
1750// if n_args==0 then there are only self/NULL and fun
1751py_obj_t rt_call_method_n(int n_args, const py_obj_t *args) {
Damien7f5dacf2013-10-10 11:24:39 +01001752 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 +01001753 return rt_call_function_n(args[n_args + 1], n_args + ((args[n_args] == NULL) ? 0 : 1), args);
1754}
1755
Damien429d7192013-10-04 19:53:11 +01001756// items are in reverse order
Damienc226dca2013-10-16 16:12:52 +01001757py_obj_t rt_build_tuple(int n_args, py_obj_t *items) {
1758 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1759 o->kind = O_TUPLE;
1760 o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args;
1761 o->u_tuple_list.len = n_args;
1762 o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc);
1763 for (int i = 0; i < n_args; i++) {
1764 o->u_tuple_list.items[i] = items[n_args - i - 1];
1765 }
1766 return o;
1767}
1768
1769// items are in reverse order
Damien429d7192013-10-04 19:53:11 +01001770py_obj_t rt_build_list(int n_args, py_obj_t *items) {
1771 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1772 o->kind = O_LIST;
Damienc226dca2013-10-16 16:12:52 +01001773 o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args;
1774 o->u_tuple_list.len = n_args;
1775 o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc);
Damien429d7192013-10-04 19:53:11 +01001776 for (int i = 0; i < n_args; i++) {
Damienc226dca2013-10-16 16:12:52 +01001777 o->u_tuple_list.items[i] = items[n_args - i - 1];
Damien429d7192013-10-04 19:53:11 +01001778 }
1779 return o;
1780}
1781
1782py_obj_t py_set_lookup(py_obj_t o_in, py_obj_t index, bool add_if_not_found) {
1783 assert(IS_O(o_in, O_SET));
1784 py_obj_base_t *o = o_in;
1785 int hash = py_obj_hash(index);
1786 int pos = hash % o->u_set.alloc;
1787 for (;;) {
1788 py_obj_t elem = o->u_set.table[pos];
1789 if (elem == NULL) {
1790 // not in table
1791 if (add_if_not_found) {
1792 if (o->u_set.used + 1 >= o->u_set.alloc) {
1793 // not enough room in table, rehash it
1794 int old_alloc = o->u_set.alloc;
1795 py_obj_t *old_table = o->u_set.table;
1796 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(o->u_set.alloc + 1);
1797 o->u_set.used = 0;
1798 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
1799 for (int i = 0; i < old_alloc; i++) {
1800 if (old_table[i] != NULL) {
1801 py_set_lookup(o, old_table[i], true);
1802 }
1803 }
1804 m_free(old_table);
1805 // restart the search for the new element
1806 pos = hash % o->u_set.alloc;
1807 } else {
1808 o->u_set.used += 1;
1809 o->u_set.table[pos] = index;
1810 return index;
1811 }
1812 } else {
1813 return NULL;
1814 }
1815 } else if (py_obj_equal(elem, index)) {
1816 // found it
1817 return elem;
1818 } else {
1819 // not yet found, keep searching in this table
1820 pos = (pos + 1) % o->u_set.alloc;
1821 }
1822 }
1823}
1824
1825py_obj_t rt_build_set(int n_args, py_obj_t *items) {
1826 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1827 o->kind = O_SET;
1828 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(n_args + 1);
1829 o->u_set.used = 0;
1830 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
1831 for (int i = 0; i < o->u_set.alloc; i++) {
1832 o->u_set.table[i] = NULL;
1833 }
1834 for (int i = 0; i < n_args; i++) {
1835 py_set_lookup(o, items[i], true);
1836 }
1837 return o;
1838}
1839
Damienc12aa462013-10-16 20:57:49 +01001840py_obj_t rt_store_set(py_obj_t set, py_obj_t item) {
1841 py_set_lookup(set, item, true);
1842 return set;
1843}
1844
Damien429d7192013-10-04 19:53:11 +01001845py_obj_t rt_build_map(int n_args) {
1846 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1847 o->kind = O_MAP;
1848 py_map_init(&o->u_map, MAP_PY_OBJ, n_args);
1849 return o;
1850}
1851
1852py_obj_t rt_store_map(py_obj_t map, py_obj_t key, py_obj_t value) {
1853 assert(IS_O(map, O_MAP)); // should always be
1854 py_map_lookup(map, key, true)->value = value;
1855 return map;
1856}
1857
Damiena3977762013-10-09 23:10:10 +01001858py_obj_t build_bound_method(py_obj_t self, py_obj_t meth) {
1859 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1860 o->kind = O_BOUND_METH;
1861 o->u_bound_meth.meth = meth;
1862 o->u_bound_meth.self = self;
1863 return o;
1864}
1865
1866py_obj_t rt_load_attr(py_obj_t base, qstr attr) {
1867 DEBUG_OP_printf("load attr %s\n", qstr_str(attr));
1868 if (IS_O(base, O_LIST) && attr == q_append) {
1869 return build_bound_method(base, fun_list_append);
1870 } else if (IS_O(base, O_CLASS)) {
1871 py_obj_base_t *o = base;
1872 py_map_elem_t *elem = py_qstr_map_lookup(o->u_class.locals, attr, false);
1873 if (elem == NULL) {
1874 goto no_attr;
1875 }
1876 return elem->value;
1877 } else if (IS_O(base, O_OBJ)) {
1878 // logic: look in obj members then class locals (TODO check this against CPython)
1879 py_obj_base_t *o = base;
1880 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false);
1881 if (elem != NULL) {
1882 // object member, always treated as a value
1883 return elem->value;
1884 }
1885 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1886 if (elem != NULL) {
1887 if (py_obj_is_callable(elem->value)) {
1888 // class member is callable so build a bound method
1889 return build_bound_method(base, elem->value);
1890 } else {
1891 // class member is a value, so just return that value
1892 return elem->value;
1893 }
1894 }
1895 goto no_attr;
1896 }
1897
1898no_attr:
Damience89a212013-10-15 22:25:17 +01001899 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 +01001900}
1901
1902void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest) {
1903 DEBUG_OP_printf("load method %s\n", qstr_str(attr));
Damien2f06c572013-11-03 18:20:56 +00001904 if (IS_O(base, O_STR)) {
1905 if (attr == q_join) {
1906 dest[1] = fun_str_join;
1907 dest[0] = base;
1908 return;
1909 } else if (attr == q_format) {
1910 dest[1] = fun_str_format;
1911 dest[0] = base;
1912 return;
1913 }
Damien4ebb32f2013-11-02 14:33:10 +00001914 } else if (IS_O(base, O_GEN_INSTANCE) && attr == q___next__) {
Damienbd254452013-10-16 20:39:12 +01001915 dest[1] = fun_gen_instance_next;
1916 dest[0] = base;
1917 return;
1918 } else if (IS_O(base, O_LIST) && attr == q_append) {
Damiena3977762013-10-09 23:10:10 +01001919 dest[1] = fun_list_append;
1920 dest[0] = base;
1921 return;
1922 } else if (IS_O(base, O_OBJ)) {
1923 // logic: look in obj members then class locals (TODO check this against CPython)
1924 py_obj_base_t *o = base;
1925 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false);
1926 if (elem != NULL) {
1927 // object member, always treated as a value
1928 dest[1] = elem->value;
1929 dest[0] = NULL;
1930 return;
1931 }
1932 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1933 if (elem != NULL) {
1934 if (py_obj_is_callable(elem->value)) {
1935 // class member is callable so build a bound method
1936 dest[1] = elem->value;
1937 dest[0] = base;
1938 return;
1939 } else {
1940 // class member is a value, so just return that value
1941 dest[1] = elem->value;
1942 dest[0] = NULL;
1943 return;
1944 }
1945 }
1946 goto no_attr;
Damiend57eba52013-11-02 23:58:14 +00001947 } else if (IS_O(base, O_USER)) {
1948 py_obj_base_t *o = base;
1949 const py_user_method_t *meth = &o->u_user.info->methods[0];
1950 for (; meth->name != NULL; meth++) {
1951 if (strcmp(meth->name, qstr_str(attr)) == 0) {
1952 if (meth->kind == 0) {
1953 dest[1] = rt_make_function_1(meth->fun);
1954 } else if (meth->kind == 1) {
1955 dest[1] = rt_make_function_2(meth->fun);
1956 } else {
1957 assert(0);
1958 }
1959 dest[0] = base;
1960 return;
1961 }
1962 }
Damiena3977762013-10-09 23:10:10 +01001963 }
1964
1965no_attr:
1966 dest[1] = rt_load_attr(base, attr);
1967 dest[0] = NULL;
1968}
1969
Damien5ac1b2e2013-10-18 19:58:12 +01001970void rt_store_attr(py_obj_t base, qstr attr, py_obj_t value) {
1971 DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value);
Damienec63cce2013-10-22 22:58:17 +01001972 if (IS_O(base, O_CLASS)) {
1973 // TODO CPython allows STORE_ATTR to a class, but is this the correct implementation?
1974 py_obj_base_t *o = base;
1975 py_qstr_map_lookup(o->u_class.locals, attr, true)->value = value;
1976 } else if (IS_O(base, O_OBJ)) {
Damiena3977762013-10-09 23:10:10 +01001977 // logic: look in class locals (no add) then obj members (add) (TODO check this against CPython)
1978 py_obj_base_t *o = base;
1979 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1980 if (elem != NULL) {
Damien5ac1b2e2013-10-18 19:58:12 +01001981 elem->value = value;
Damiena3977762013-10-09 23:10:10 +01001982 } else {
Damienec63cce2013-10-22 22:58:17 +01001983 py_qstr_map_lookup(o->u_obj.members, attr, true)->value = value;
Damiena3977762013-10-09 23:10:10 +01001984 }
1985 } else {
1986 printf("?AttributeError: '%s' object has no attribute '%s'\n", py_obj_get_type_str(base), qstr_str(attr));
1987 assert(0);
1988 }
1989}
1990
Damien429d7192013-10-04 19:53:11 +01001991void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t value) {
Damien5ac1b2e2013-10-18 19:58:12 +01001992 DEBUG_OP_printf("store subscr %p[%p] <- %p\n", base, index, value);
Damienc226dca2013-10-16 16:12:52 +01001993 if (IS_O(base, O_LIST)) {
Damien429d7192013-10-04 19:53:11 +01001994 // list store
Damienc226dca2013-10-16 16:12:52 +01001995 uint i = get_index(base, index);
1996 ((py_obj_base_t*)base)->u_tuple_list.items[i] = value;
Damien429d7192013-10-04 19:53:11 +01001997 } else if (IS_O(base, O_MAP)) {
1998 // map store
1999 py_map_lookup(base, index, true)->value = value;
2000 } else {
2001 assert(0);
2002 }
2003}
2004
Damience89a212013-10-15 22:25:17 +01002005py_obj_t rt_getiter(py_obj_t o_in) {
Damienbd254452013-10-16 20:39:12 +01002006 if (IS_O(o_in, O_GEN_INSTANCE)) {
2007 return o_in;
2008 } else if (IS_O(o_in, O_RANGE)) {
Damience89a212013-10-15 22:25:17 +01002009 py_obj_base_t *o = o_in;
2010 return py_obj_new_range_iterator(o->u_range.start, o->u_range.stop, o->u_range.step);
Damienc226dca2013-10-16 16:12:52 +01002011 } else if (IS_O(o_in, O_TUPLE)) {
2012 return py_obj_new_tuple_iterator(o_in, 0);
2013 } else if (IS_O(o_in, O_LIST)) {
2014 return py_obj_new_list_iterator(o_in, 0);
Damience89a212013-10-15 22:25:17 +01002015 } else {
2016 nlr_jump(py_obj_new_exception_2(q_TypeError, "'%s' object is not iterable", py_obj_get_type_str(o_in), NULL));
2017 }
2018}
2019
2020py_obj_t rt_iternext(py_obj_t o_in) {
Damienbd254452013-10-16 20:39:12 +01002021 if (IS_O(o_in, O_GEN_INSTANCE)) {
2022 py_obj_base_t *self = o_in;
Damien03c9cfb2013-11-05 22:06:08 +00002023 //py_obj_base_t *fun = self->u_gen_instance.state[0];
2024 //assert(fun->kind == O_FUN_BC);
2025 bool yield = py_execute_byte_code_2(&self->u_gen_instance.ip, &self->u_gen_instance.state[1], &self->u_gen_instance.sp);
Damienbd254452013-10-16 20:39:12 +01002026 if (yield) {
2027 return *self->u_gen_instance.sp;
2028 } else {
2029 if (*self->u_gen_instance.sp == py_const_none) {
2030 return py_const_stop_iteration;
2031 } else {
2032 // TODO return StopIteration with value *self->u_gen_instance.sp
2033 return py_const_stop_iteration;
2034 }
2035 }
2036
2037 } else if (IS_O(o_in, O_RANGE_IT)) {
Damience89a212013-10-15 22:25:17 +01002038 py_obj_base_t *o = o_in;
2039 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)) {
2040 py_obj_t o_out = TO_SMALL_INT(o->u_range_it.cur);
2041 o->u_range_it.cur += o->u_range_it.step;
2042 return o_out;
2043 } else {
2044 return py_const_stop_iteration;
2045 }
Damienbd254452013-10-16 20:39:12 +01002046
Damienc226dca2013-10-16 16:12:52 +01002047 } else if (IS_O(o_in, O_TUPLE_IT) || IS_O(o_in, O_LIST_IT)) {
2048 py_obj_base_t *o = o_in;
2049 if (o->u_tuple_list_it.cur < o->u_tuple_list_it.obj->u_tuple_list.len) {
2050 py_obj_t o_out = o->u_tuple_list_it.obj->u_tuple_list.items[o->u_tuple_list_it.cur];
2051 o->u_tuple_list_it.cur += 1;
2052 return o_out;
2053 } else {
2054 return py_const_stop_iteration;
2055 }
Damienbd254452013-10-16 20:39:12 +01002056
Damience89a212013-10-15 22:25:17 +01002057 } else {
2058 nlr_jump(py_obj_new_exception_2(q_TypeError, "? '%s' object is not iterable", py_obj_get_type_str(o_in), NULL));
2059 }
2060}
2061
Damien6ba13142013-11-02 20:34:54 +00002062// these must correspond to the respective enum
Damiendf4b4f32013-10-19 18:28:01 +01002063void *const rt_fun_table[RT_F_NUMBER_OF] = {
Damien6ba13142013-11-02 20:34:54 +00002064 rt_load_const_dec,
Damien429d7192013-10-04 19:53:11 +01002065 rt_load_const_str,
2066 rt_load_name,
2067 rt_load_global,
Damien7f5dacf2013-10-10 11:24:39 +01002068 rt_load_build_class,
Damien429d7192013-10-04 19:53:11 +01002069 rt_load_attr,
2070 rt_load_method,
2071 rt_store_name,
Damien7f5dacf2013-10-10 11:24:39 +01002072 rt_store_attr,
Damien429d7192013-10-04 19:53:11 +01002073 rt_store_subscr,
2074 rt_is_true,
2075 rt_unary_op,
Damiend2755ec2013-10-16 23:58:48 +01002076 rt_build_tuple,
Damien429d7192013-10-04 19:53:11 +01002077 rt_build_list,
Damiend2755ec2013-10-16 23:58:48 +01002078 rt_list_append,
Damien429d7192013-10-04 19:53:11 +01002079 rt_build_map,
2080 rt_store_map,
2081 rt_build_set,
Damiend2755ec2013-10-16 23:58:48 +01002082 rt_store_set,
Damien429d7192013-10-04 19:53:11 +01002083 rt_make_function_from_id,
Damieneb19efb2013-10-10 22:06:54 +01002084 rt_call_function_n,
Damien7f5dacf2013-10-10 11:24:39 +01002085 rt_call_method_n,
Damien429d7192013-10-04 19:53:11 +01002086 rt_binary_op,
2087 rt_compare_op,
Damiend2755ec2013-10-16 23:58:48 +01002088 rt_getiter,
2089 rt_iternext,
Damien429d7192013-10-04 19:53:11 +01002090};
2091
2092/*
2093void rt_f_vector(rt_fun_kind_t fun_kind) {
2094 (rt_f_table[fun_kind])();
2095}
2096*/
Damienec63cce2013-10-22 22:58:17 +01002097
2098// temporary way of making C modules
2099// hack: use class to mimic a module
2100
Damien8b3a7c22013-10-23 20:20:17 +01002101py_obj_t py_module_new(void) {
Damienec63cce2013-10-22 22:58:17 +01002102 py_obj_base_t *o = m_new(py_obj_base_t, 1);
2103 o->kind = O_CLASS;
2104 o->u_class.locals = py_map_new(MAP_QSTR, 0);
2105 return o;
2106}