blob: 81881c4038099e4ce7a6e1453705b638ffd4976b [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
Damien7f5dacf2013-10-10 11:24:39 +010018#if 0 // print debugging info
Damiena1ddfcc2013-10-10 23:25:50 +010019#define DEBUG_PRINT (1)
Damien0446a0d2013-11-17 13:16:36 +000020#define WRITE_CODE (1)
Damien7f5dacf2013-10-10 11:24:39 +010021#define DEBUG_printf(args...) printf(args)
22#define DEBUG_OP_printf(args...) printf(args)
23#else // don't print debugging info
Damiena3977762013-10-09 23:10:10 +010024#define DEBUG_printf(args...) (void)0
Damien429d7192013-10-04 19:53:11 +010025#define DEBUG_OP_printf(args...) (void)0
Damien7f5dacf2013-10-10 11:24:39 +010026#endif
Damien429d7192013-10-04 19:53:11 +010027
Damien429d7192013-10-04 19:53:11 +010028typedef machine_int_t py_small_int_t;
29
30#define IS_O(o, k) (((((py_small_int_t)(o)) & 1) == 0) && (((py_obj_base_t*)(o))->kind == (k)))
31#define IS_SMALL_INT(o) (((py_small_int_t)(o)) & 1)
32#define FROM_SMALL_INT(o) (((py_small_int_t)(o)) >> 1)
33#define TO_SMALL_INT(o) ((py_obj_t)(((o) << 1) | 1))
34
Damien3ef4abb2013-10-12 16:53:13 +010035#if MICROPY_ENABLE_FLOAT
Damien7410e442013-11-02 19:47:57 +000036typedef machine_float_t py_float_t;
Damien429d7192013-10-04 19:53:11 +010037#endif
38
39typedef enum {
40 O_CONST,
41 O_STR,
Damien3ef4abb2013-10-12 16:53:13 +010042#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +010043 O_FLOAT,
Damien7410e442013-11-02 19:47:57 +000044 O_COMPLEX,
Damien429d7192013-10-04 19:53:11 +010045#endif
Damience89a212013-10-15 22:25:17 +010046 O_EXCEPTION_0,
Damienf086ecf2013-10-22 16:05:11 +010047 O_EXCEPTION_N,
Damience89a212013-10-15 22:25:17 +010048 O_RANGE,
49 O_RANGE_IT,
Damien429d7192013-10-04 19:53:11 +010050 O_FUN_0,
51 O_FUN_1,
52 O_FUN_2,
53 O_FUN_N,
Damien2f06c572013-11-03 18:20:56 +000054 O_FUN_VAR,
Damien429d7192013-10-04 19:53:11 +010055 O_FUN_BC,
Damien826005c2013-10-05 23:17:28 +010056 O_FUN_ASM,
Damienbd254452013-10-16 20:39:12 +010057 O_GEN_WRAP,
58 O_GEN_INSTANCE,
Damien429d7192013-10-04 19:53:11 +010059 O_BOUND_METH,
Damienc226dca2013-10-16 16:12:52 +010060 O_TUPLE,
Damien429d7192013-10-04 19:53:11 +010061 O_LIST,
Damienc226dca2013-10-16 16:12:52 +010062 O_TUPLE_IT,
63 O_LIST_IT,
Damien429d7192013-10-04 19:53:11 +010064 O_SET,
65 O_MAP,
66 O_CLASS,
Damiena3977762013-10-09 23:10:10 +010067 O_OBJ,
Damiend57eba52013-11-02 23:58:14 +000068 O_USER,
Damien429d7192013-10-04 19:53:11 +010069} py_obj_kind_t;
70
71typedef enum {
72 MAP_QSTR,
73 MAP_PY_OBJ,
74} py_map_kind_t;
75
76typedef struct _py_map_elem_t {
77 py_obj_t key;
78 py_obj_t value;
79} py_map_elem_t;
80
81typedef struct _py_map_t {
Damienf086ecf2013-10-22 16:05:11 +010082 struct {
83 py_map_kind_t kind : 1;
84 machine_uint_t used : (8 * BYTES_PER_WORD - 1);
85 };
Damien429d7192013-10-04 19:53:11 +010086 machine_uint_t alloc;
Damien429d7192013-10-04 19:53:11 +010087 py_map_elem_t *table;
88} py_map_t;
89
Damiena3977762013-10-09 23:10:10 +010090typedef struct _py_obj_base_t py_obj_base_t;
91
92struct _py_obj_base_t {
Damien429d7192013-10-04 19:53:11 +010093 py_obj_kind_t kind;
94 union {
95 const char *id;
96 qstr u_str;
Damien3ef4abb2013-10-12 16:53:13 +010097#if MICROPY_ENABLE_FLOAT
Damien7410e442013-11-02 19:47:57 +000098 py_float_t u_float; // for O_FLOAT
99 struct { // for O_COMPLEX
100 py_float_t real;
101 py_float_t imag;
102 } u_complex;
Damien429d7192013-10-04 19:53:11 +0100103#endif
Damience89a212013-10-15 22:25:17 +0100104 struct { // for O_EXCEPTION_0
105 qstr id;
106 } u_exc0;
Damienf086ecf2013-10-22 16:05:11 +0100107 struct { // for O_EXCEPTION_N
108 // TODO make generic object or something
Damience89a212013-10-15 22:25:17 +0100109 qstr id;
Damienf086ecf2013-10-22 16:05:11 +0100110 int n_args;
111 const void **args;
112 } u_exc_n;
Damience89a212013-10-15 22:25:17 +0100113 struct { // for O_RANGE
114 // TODO make generic object or something
115 machine_int_t start;
116 machine_int_t stop;
117 machine_int_t step;
118 } u_range;
119 struct { // for O_RANGE_IT
120 // TODO make generic object or something
121 machine_int_t cur;
122 machine_int_t stop;
123 machine_int_t step;
124 } u_range_it;
Damien2f06c572013-11-03 18:20:56 +0000125 struct { // for O_FUN_[012N], O_FUN_VAR
Damien429d7192013-10-04 19:53:11 +0100126 int n_args;
Damien826005c2013-10-05 23:17:28 +0100127 void *fun;
Damien429d7192013-10-04 19:53:11 +0100128 } u_fun;
129 struct { // for O_FUN_BC
Damien826005c2013-10-05 23:17:28 +0100130 int n_args;
Damien40fdfe32013-11-05 22:16:22 +0000131 uint n_state;
Damien429d7192013-10-04 19:53:11 +0100132 byte *code;
Damien429d7192013-10-04 19:53:11 +0100133 } u_fun_bc;
Damien826005c2013-10-05 23:17:28 +0100134 struct { // for O_FUN_ASM
135 int n_args;
136 void *fun;
137 } u_fun_asm;
Damienbd254452013-10-16 20:39:12 +0100138 struct { // for O_GEN_WRAP
139 int n_state;
140 py_obj_base_t *fun;
141 } u_gen_wrap;
142 struct { // for O_GEN_INSTANCE
143 py_obj_t *state;
144 const byte *ip;
145 py_obj_t *sp;
146 } u_gen_instance;
Damien429d7192013-10-04 19:53:11 +0100147 struct { // for O_BOUND_METH
148 py_obj_t meth;
149 py_obj_t self;
150 } u_bound_meth;
Damienc226dca2013-10-16 16:12:52 +0100151 struct { // for O_TUPLE, O_LIST
Damienf086ecf2013-10-22 16:05:11 +0100152 machine_uint_t alloc;
153 machine_uint_t len;
Damien429d7192013-10-04 19:53:11 +0100154 py_obj_t *items;
Damienc226dca2013-10-16 16:12:52 +0100155 } u_tuple_list;
156 struct { // for O_TUPLE_IT, O_LIST_IT
157 py_obj_base_t *obj;
Damienf086ecf2013-10-22 16:05:11 +0100158 machine_uint_t cur;
Damienc226dca2013-10-16 16:12:52 +0100159 } u_tuple_list_it;
Damien429d7192013-10-04 19:53:11 +0100160 struct { // for O_SET
Damienf086ecf2013-10-22 16:05:11 +0100161 machine_uint_t alloc;
162 machine_uint_t used;
Damien429d7192013-10-04 19:53:11 +0100163 py_obj_t *table;
164 } u_set;
165 py_map_t u_map; // for O_MAP
Damien429d7192013-10-04 19:53:11 +0100166 struct { // for O_CLASS
Damiena3977762013-10-09 23:10:10 +0100167 py_map_t *locals;
Damien429d7192013-10-04 19:53:11 +0100168 } u_class;
Damiena3977762013-10-09 23:10:10 +0100169 struct { // for O_OBJ
170 py_obj_base_t *class; // points to a O_CLASS object
171 py_map_t *members;
172 } u_obj;
Damiend57eba52013-11-02 23:58:14 +0000173 struct { // for O_USER
174 const py_user_info_t *info;
175 machine_uint_t data1;
176 machine_uint_t data2;
177 } u_user;
Damien429d7192013-10-04 19:53:11 +0100178 };
Damiena3977762013-10-09 23:10:10 +0100179};
Damien429d7192013-10-04 19:53:11 +0100180
Damien4ebb32f2013-11-02 14:33:10 +0000181static qstr q_append;
182static qstr q_join;
Damien2f06c572013-11-03 18:20:56 +0000183static qstr q_format;
Damien4ebb32f2013-11-02 14:33:10 +0000184static qstr q___build_class__;
185static qstr q___next__;
186static qstr q_AttributeError;
187static qstr q_IndexError;
188static qstr q_KeyError;
189static qstr q_NameError;
190static qstr q_TypeError;
Damien7410e442013-11-02 19:47:57 +0000191static qstr q_SyntaxError;
Damien4ebb32f2013-11-02 14:33:10 +0000192
Damien429d7192013-10-04 19:53:11 +0100193py_obj_t py_const_none;
194py_obj_t py_const_false;
195py_obj_t py_const_true;
Damience89a212013-10-15 22:25:17 +0100196py_obj_t py_const_stop_iteration;
Damien429d7192013-10-04 19:53:11 +0100197
Damieneb19efb2013-10-10 22:06:54 +0100198// locals and globals need to be pointers because they can be the same in outer module scope
Damien4ebb32f2013-11-02 14:33:10 +0000199static py_map_t *map_locals;
200static py_map_t *map_globals;
201static py_map_t map_builtins;
Damien429d7192013-10-04 19:53:11 +0100202
203// approximatelly doubling primes; made with Mathematica command: Table[Prime[Floor[(1.7)^n]], {n, 3, 24}]
204static 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};
205
206int get_doubling_prime_greater_or_equal_to(int x) {
207 for (int i = 0; i < sizeof(doubling_primes) / sizeof(int); i++) {
208 if (doubling_primes[i] >= x) {
209 return doubling_primes[i];
210 }
211 }
212 // ran out of primes in the table!
213 // return something sensible, at least make it odd
214 return x | 1;
215}
216
217void py_map_init(py_map_t *map, py_map_kind_t kind, int n) {
218 map->kind = kind;
Damien429d7192013-10-04 19:53:11 +0100219 map->used = 0;
Damienf086ecf2013-10-22 16:05:11 +0100220 map->alloc = get_doubling_prime_greater_or_equal_to(n + 1);
Damien5ac1b2e2013-10-18 19:58:12 +0100221 map->table = m_new0(py_map_elem_t, map->alloc);
Damien429d7192013-10-04 19:53:11 +0100222}
223
224py_map_t *py_map_new(py_map_kind_t kind, int n) {
225 py_map_t *map = m_new(py_map_t, 1);
226 py_map_init(map, kind, n);
227 return map;
228}
229
Damien5ac1b2e2013-10-18 19:58:12 +0100230machine_int_t py_obj_hash(py_obj_t o_in) {
231 if (o_in == py_const_false) {
232 return 0; // needs to hash to same as the integer 0, since False==0
233 } else if (o_in == py_const_true) {
234 return 1; // needs to hash to same as the integer 1, since True==1
235 } else if (IS_SMALL_INT(o_in)) {
Damien429d7192013-10-04 19:53:11 +0100236 return FROM_SMALL_INT(o_in);
Damien5ac1b2e2013-10-18 19:58:12 +0100237 } else if (IS_O(o_in, O_CONST)) {
238 return (machine_int_t)o_in;
Damien429d7192013-10-04 19:53:11 +0100239 } else if (IS_O(o_in, O_STR)) {
240 return ((py_obj_base_t*)o_in)->u_str;
241 } else {
242 assert(0);
243 return 0;
244 }
245}
246
Damien5ac1b2e2013-10-18 19:58:12 +0100247// this function implements the '==' operator (and so the inverse of '!=')
248// from the python language reference:
249// "The objects need not have the same type. If both are numbers, they are converted
250// to a common type. Otherwise, the == and != operators always consider objects of
251// different types to be unequal."
252// note also that False==0 and True==1 are true expressions
Damien429d7192013-10-04 19:53:11 +0100253bool py_obj_equal(py_obj_t o1, py_obj_t o2) {
254 if (o1 == o2) {
255 return true;
Damien5ac1b2e2013-10-18 19:58:12 +0100256 } else if (IS_SMALL_INT(o1) || IS_SMALL_INT(o2)) {
257 if (IS_SMALL_INT(o1) && IS_SMALL_INT(o2)) {
258 return false;
259 } else {
260 if (IS_SMALL_INT(o2)) {
261 py_obj_t temp = o1; o1 = o2; o2 = temp;
262 }
263 // o1 is the SMALL_INT, o2 is not
264 py_small_int_t val = FROM_SMALL_INT(o1);
265 if (o2 == py_const_false) {
266 return val == 0;
267 } else if (o2 == py_const_true) {
268 return val == 1;
269 } else {
270 return false;
271 }
272 }
Damien429d7192013-10-04 19:53:11 +0100273 } else if (IS_O(o1, O_STR) && IS_O(o2, O_STR)) {
274 return ((py_obj_base_t*)o1)->u_str == ((py_obj_base_t*)o2)->u_str;
275 } else {
276 assert(0);
277 return false;
278 }
279}
280
281py_map_elem_t* py_map_lookup_helper(py_map_t *map, py_obj_t index, bool add_if_not_found) {
282 bool is_map_py_obj = (map->kind == MAP_PY_OBJ);
283 machine_uint_t hash;
284 if (is_map_py_obj) {
285 hash = py_obj_hash(index);
286 } else {
287 hash = (machine_uint_t)index;
288 }
289 uint pos = hash % map->alloc;
290 for (;;) {
291 py_map_elem_t *elem = &map->table[pos];
292 if (elem->key == NULL) {
293 // not in table
294 if (add_if_not_found) {
295 if (map->used + 1 >= map->alloc) {
296 // not enough room in table, rehash it
297 int old_alloc = map->alloc;
298 py_map_elem_t *old_table = map->table;
299 map->alloc = get_doubling_prime_greater_or_equal_to(map->alloc + 1);
300 map->used = 0;
Damien5ac1b2e2013-10-18 19:58:12 +0100301 map->table = m_new0(py_map_elem_t, map->alloc);
Damien429d7192013-10-04 19:53:11 +0100302 for (int i = 0; i < old_alloc; i++) {
303 if (old_table[i].key != NULL) {
304 py_map_lookup_helper(map, old_table[i].key, true)->value = old_table[i].value;
305 }
306 }
307 m_free(old_table);
308 // restart the search for the new element
309 pos = hash % map->alloc;
310 } else {
311 map->used += 1;
312 elem->key = index;
313 return elem;
314 }
315 } else {
316 return NULL;
317 }
318 } else if (elem->key == index || (is_map_py_obj && py_obj_equal(elem->key, index))) {
319 // found it
Damien5ac1b2e2013-10-18 19:58:12 +0100320 /* it seems CPython does not replace the index; try x={True:'true'};x[1]='one';x
Damien429d7192013-10-04 19:53:11 +0100321 if (add_if_not_found) {
322 elem->key = index;
323 }
Damien5ac1b2e2013-10-18 19:58:12 +0100324 */
Damien429d7192013-10-04 19:53:11 +0100325 return elem;
326 } else {
327 // not yet found, keep searching in this table
328 pos = (pos + 1) % map->alloc;
329 }
330 }
331}
332
333py_map_elem_t* py_qstr_map_lookup(py_map_t *map, qstr index, bool add_if_not_found) {
334 py_obj_t o = (py_obj_t)(machine_uint_t)index;
335 return py_map_lookup_helper(map, o, add_if_not_found);
336}
337
338py_map_elem_t* py_map_lookup(py_obj_t o, py_obj_t index, bool add_if_not_found) {
339 assert(IS_O(o, O_MAP));
340 return py_map_lookup_helper(&((py_obj_base_t *)o)->u_map, index, add_if_not_found);
341}
342
343static bool fit_small_int(py_small_int_t o) {
344 return true;
345}
346
Damien4ebb32f2013-11-02 14:33:10 +0000347py_obj_t py_obj_new_int(machine_int_t value) {
Damien6f08f8c2013-10-23 22:17:26 +0100348 return TO_SMALL_INT(value);
349}
350
Damien429d7192013-10-04 19:53:11 +0100351py_obj_t py_obj_new_const(const char *id) {
352 py_obj_base_t *o = m_new(py_obj_base_t, 1);
353 o->kind = O_CONST;
354 o->id = id;
355 return (py_obj_t)o;
356}
357
358py_obj_t py_obj_new_str(qstr qstr) {
359 py_obj_base_t *o = m_new(py_obj_base_t, 1);
360 o->kind = O_STR;
361 o->u_str = qstr;
362 return (py_obj_t)o;
363}
364
Damien3ef4abb2013-10-12 16:53:13 +0100365#if MICROPY_ENABLE_FLOAT
Damien7410e442013-11-02 19:47:57 +0000366py_obj_t py_obj_new_float(py_float_t val) {
Damien429d7192013-10-04 19:53:11 +0100367 py_obj_base_t *o = m_new(py_obj_base_t, 1);
368 o->kind = O_FLOAT;
Damien7410e442013-11-02 19:47:57 +0000369 o->u_float = val;
370 return (py_obj_t)o;
371}
372
373py_obj_t py_obj_new_complex(py_float_t real, py_float_t imag) {
374 py_obj_base_t *o = m_new(py_obj_base_t, 1);
375 o->kind = O_COMPLEX;
376 o->u_complex.real = real;
377 o->u_complex.imag = imag;
Damien429d7192013-10-04 19:53:11 +0100378 return (py_obj_t)o;
379}
380#endif
381
Damience89a212013-10-15 22:25:17 +0100382py_obj_t py_obj_new_exception_0(qstr id) {
383 py_obj_base_t *o = m_new(py_obj_base_t, 1);
384 o->kind = O_EXCEPTION_0;
385 o->u_exc0.id = id;
386 return (py_obj_t)o;
387}
388
389py_obj_t py_obj_new_exception_2(qstr id, const char *fmt, const char *s1, const char *s2) {
390 py_obj_base_t *o = m_new(py_obj_base_t, 1);
Damienf086ecf2013-10-22 16:05:11 +0100391 o->kind = O_EXCEPTION_N;
392 o->u_exc_n.id = id;
393 o->u_exc_n.n_args = 3;
394 o->u_exc_n.args = m_new(const void*, 3);
395 o->u_exc_n.args[0] = fmt;
396 o->u_exc_n.args[1] = s1;
397 o->u_exc_n.args[2] = s2;
Damience89a212013-10-15 22:25:17 +0100398 return (py_obj_t)o;
399}
400
401// range is a class and instances are immutable sequence objects
402py_obj_t py_obj_new_range(int start, int stop, int step) {
403 py_obj_base_t *o = m_new(py_obj_base_t, 1);
404 o->kind = O_RANGE;
405 o->u_range.start = start;
406 o->u_range.stop = stop;
407 o->u_range.step = step;
408 return o;
409}
410
411py_obj_t py_obj_new_range_iterator(int cur, int stop, int step) {
412 py_obj_base_t *o = m_new(py_obj_base_t, 1);
413 o->kind = O_RANGE_IT;
414 o->u_range_it.cur = cur;
415 o->u_range_it.stop = stop;
416 o->u_range_it.step = step;
417 return o;
418}
419
Damienc226dca2013-10-16 16:12:52 +0100420py_obj_t py_obj_new_tuple_iterator(py_obj_base_t *tuple, int cur) {
421 py_obj_base_t *o = m_new(py_obj_base_t, 1);
422 o->kind = O_TUPLE_IT;
423 o->u_tuple_list_it.obj = tuple;
424 o->u_tuple_list_it.cur = cur;
425 return o;
426}
427
428py_obj_t py_obj_new_list_iterator(py_obj_base_t *list, int cur) {
429 py_obj_base_t *o = m_new(py_obj_base_t, 1);
430 o->kind = O_LIST_IT;
431 o->u_tuple_list_it.obj = list;
432 o->u_tuple_list_it.cur = cur;
433 return o;
434}
435
Damiend57eba52013-11-02 23:58:14 +0000436py_obj_t py_obj_new_user(const py_user_info_t *info, machine_uint_t data1, machine_uint_t data2) {
437 py_obj_base_t *o = m_new(py_obj_base_t, 1);
438 o->kind = O_USER;
439 // TODO should probably parse the info to turn strings to qstr's, and wrap functions in O_FUN_N objects
440 // that'll take up some memory. maybe we can lazily do the O_FUN_N: leave it a ptr to a C function, and
441 // only when the method is looked-up do we change that to the O_FUN_N object.
442 o->u_user.info = info;
443 o->u_user.data1 = data1;
444 o->u_user.data2 = data2;
445 return o;
446}
447
Damien33af3bf2013-11-03 14:39:47 +0000448const char *py_obj_get_type_str(py_obj_t o_in) {
449 if (IS_SMALL_INT(o_in)) {
450 return "int";
451 } else {
452 py_obj_base_t *o = o_in;
453 switch (o->kind) {
454 case O_CONST:
455 if (o == py_const_none) {
456 return "NoneType";
457 } else {
458 return "bool";
459 }
460 case O_STR:
461 return "str";
462#if MICROPY_ENABLE_FLOAT
463 case O_FLOAT:
464 return "float";
465#endif
466 case O_FUN_0:
467 case O_FUN_1:
468 case O_FUN_2:
469 case O_FUN_N:
Damien2f06c572013-11-03 18:20:56 +0000470 case O_FUN_VAR:
Damien33af3bf2013-11-03 14:39:47 +0000471 case O_FUN_BC:
472 return "function";
473 case O_GEN_INSTANCE:
474 return "generator";
475 case O_TUPLE:
476 return "tuple";
477 case O_LIST:
478 return "list";
479 case O_TUPLE_IT:
480 return "tuple_iterator";
481 case O_LIST_IT:
482 return "list_iterator";
483 case O_SET:
484 return "set";
485 case O_MAP:
486 return "dict";
487 case O_OBJ:
488 {
489 py_map_elem_t *qn = py_qstr_map_lookup(o->u_obj.class->u_class.locals, qstr_from_str_static("__qualname__"), false);
490 assert(qn != NULL);
491 assert(IS_O(qn->value, O_STR));
492 return qstr_str(((py_obj_base_t*)qn->value)->u_str);
493 }
494 case O_USER:
495 return o->u_user.info->type_name;
496 default:
497 assert(0);
498 return "UnknownType";
499 }
500 }
501}
502
503int rt_is_true(py_obj_t arg) {
504 DEBUG_OP_printf("is true %p\n", arg);
505 if (IS_SMALL_INT(arg)) {
506 if (FROM_SMALL_INT(arg) == 0) {
507 return 0;
508 } else {
509 return 1;
510 }
511 } else if (arg == py_const_none) {
512 return 0;
513 } else if (arg == py_const_false) {
514 return 0;
515 } else if (arg == py_const_true) {
516 return 1;
517 } else {
518 assert(0);
519 return 0;
520 }
521}
522
523machine_int_t py_obj_get_int(py_obj_t arg) {
524 if (arg == py_const_false) {
525 return 0;
526 } else if (arg == py_const_true) {
527 return 1;
528 } else if (IS_SMALL_INT(arg)) {
529 return FROM_SMALL_INT(arg);
530 } else {
531 assert(0);
532 return 0;
533 }
534}
535
536#if MICROPY_ENABLE_FLOAT
537machine_float_t py_obj_get_float(py_obj_t arg) {
538 if (arg == py_const_false) {
539 return 0;
540 } else if (arg == py_const_true) {
541 return 1;
542 } else if (IS_SMALL_INT(arg)) {
543 return FROM_SMALL_INT(arg);
544 } else if (IS_O(arg, O_FLOAT)) {
545 return ((py_obj_base_t*)arg)->u_float;
546 } else {
547 assert(0);
548 return 0;
549 }
550}
551
552void py_obj_get_complex(py_obj_t arg, py_float_t *real, py_float_t *imag) {
553 if (arg == py_const_false) {
554 *real = 0;
555 *imag = 0;
556 } else if (arg == py_const_true) {
557 *real = 1;
558 *imag = 0;
559 } else if (IS_SMALL_INT(arg)) {
560 *real = FROM_SMALL_INT(arg);
561 *imag = 0;
562 } else if (IS_O(arg, O_FLOAT)) {
563 *real = ((py_obj_base_t*)arg)->u_float;
564 *imag = 0;
565 } else if (IS_O(arg, O_COMPLEX)) {
566 *real = ((py_obj_base_t*)arg)->u_complex.real;
567 *imag = ((py_obj_base_t*)arg)->u_complex.imag;
568 } else {
569 assert(0);
570 *real = 0;
571 *imag = 0;
572 }
573}
574#endif
575
576qstr py_obj_get_qstr(py_obj_t arg) {
577 if (IS_O(arg, O_STR)) {
578 return ((py_obj_base_t*)arg)->u_str;
579 } else {
580 assert(0);
581 return 0;
582 }
583}
584
585py_obj_t *py_obj_get_array_fixed_n(py_obj_t o_in, machine_int_t n) {
586 if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) {
587 py_obj_base_t *o = o_in;
588 if (o->u_tuple_list.len != n) {
589 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));
590 }
591 return o->u_tuple_list.items;
592 } else {
593 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));
594 }
595}
596
Damiend57eba52013-11-02 23:58:14 +0000597void py_user_get_data(py_obj_t o, machine_uint_t *data1, machine_uint_t *data2) {
598 assert(IS_O(o, O_USER));
599 if (data1 != NULL) {
600 *data1 = ((py_obj_base_t*)o)->u_user.data1;
601 }
602 if (data2 != NULL) {
603 *data2 = ((py_obj_base_t*)o)->u_user.data2;
604 }
605}
606
607void py_user_set_data(py_obj_t o, machine_uint_t data1, machine_uint_t data2) {
608 assert(IS_O(o, O_USER));
609 ((py_obj_base_t*)o)->u_user.data1 = data1;
610 ((py_obj_base_t*)o)->u_user.data2 = data2;
611}
612
Damien2f06c572013-11-03 18:20:56 +0000613void printf_wrapper(void *env, const char *fmt, ...) {
614 va_list args;
615 va_start(args, fmt);
616 vprintf(fmt, args);
617 va_end(args);
618}
619
620void vstr_printf_wrapper(void *env, const char *fmt, ...) {
621 va_list args;
622 va_start(args, fmt);
623 vstr_vprintf(env, fmt, args);
624 va_end(args);
625}
626
627void py_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, py_obj_t o_in) {
628 if (IS_SMALL_INT(o_in)) {
629 print(env, "%d", (int)FROM_SMALL_INT(o_in));
630 } else {
631 py_obj_base_t *o = o_in;
632 switch (o->kind) {
633 case O_CONST:
634 print(env, "%s", o->id);
635 break;
636 case O_STR:
637 // TODO need to escape chars etc
638 print(env, "'%s'", qstr_str(o->u_str));
639 break;
640#if MICROPY_ENABLE_FLOAT
641 case O_FLOAT:
642 print(env, "%.8g", o->u_float);
643 break;
644 case O_COMPLEX:
645 if (o->u_complex.real == 0) {
646 print(env, "%.8gj", o->u_complex.imag);
647 } else {
648 print(env, "(%.8g+%.8gj)", o->u_complex.real, o->u_complex.imag);
649 }
650 break;
651#endif
652 case O_EXCEPTION_0:
653 print(env, "%s", qstr_str(o->u_exc0.id));
654 break;
655 case O_EXCEPTION_N:
656 print(env, "%s: ", qstr_str(o->u_exc_n.id));
657 print(env, o->u_exc_n.args[0], o->u_exc_n.args[1], o->u_exc_n.args[2]);
658 break;
659 case O_GEN_INSTANCE:
660 print(env, "<generator object 'fun-name' at %p>", o);
661 break;
662 case O_TUPLE:
663 print(env, "(");
664 for (int i = 0; i < o->u_tuple_list.len; i++) {
665 if (i > 0) {
666 print(env, ", ");
667 }
668 py_obj_print_helper(print, env, o->u_tuple_list.items[i]);
669 }
670 if (o->u_tuple_list.len == 1) {
671 print(env, ",");
672 }
673 print(env, ")");
674 break;
675 case O_LIST:
676 print(env, "[");
677 for (int i = 0; i < o->u_tuple_list.len; i++) {
678 if (i > 0) {
679 print(env, ", ");
680 }
681 py_obj_print_helper(print, env, o->u_tuple_list.items[i]);
682 }
683 print(env, "]");
684 break;
685 case O_SET:
686 {
687 bool first = true;
688 print(env, "{");
689 for (int i = 0; i < o->u_set.alloc; i++) {
690 if (o->u_set.table[i] != NULL) {
691 if (!first) {
692 print(env, ", ");
693 }
694 first = false;
695 py_obj_print_helper(print, env, o->u_set.table[i]);
696 }
697 }
698 print(env, "}");
699 break;
700 }
701 case O_MAP:
702 {
703 bool first = true;
704 print(env, "{");
705 for (int i = 0; i < o->u_map.alloc; i++) {
706 if (o->u_map.table[i].key != NULL) {
707 if (!first) {
708 print(env, ", ");
709 }
710 first = false;
711 py_obj_print_helper(print, env, o->u_map.table[i].key);
712 print(env, ": ");
713 py_obj_print_helper(print, env, o->u_map.table[i].value);
714 }
715 }
716 print(env, "}");
717 break;
718 }
719 case O_USER:
720 o->u_user.info->print(o_in);
721 break;
722 default:
723 print(env, "<? %d>", o->kind);
724 assert(0);
725 }
726 }
727}
728
Damien4ebb32f2013-11-02 14:33:10 +0000729py_obj_t rt_str_join(py_obj_t self_in, py_obj_t arg) {
730 assert(IS_O(self_in, O_STR));
731 py_obj_base_t *self = self_in;
732 int required_len = strlen(qstr_str(self->u_str));
733
734 // process arg, count required chars
735 if (!IS_O(arg, O_TUPLE) && !IS_O(arg, O_LIST)) {
736 goto bad_arg;
737 }
738 py_obj_base_t *tuple_list = arg;
739 for (int i = 0; i < tuple_list->u_tuple_list.len; i++) {
740 if (!IS_O(tuple_list->u_tuple_list.items[i], O_STR)) {
741 goto bad_arg;
742 }
743 required_len += strlen(qstr_str(((py_obj_base_t*)tuple_list->u_tuple_list.items[i])->u_str));
744 }
745
746 // make joined string
747 char *joined_str = m_new(char, required_len + 1);
748 joined_str[0] = 0;
749 for (int i = 0; i < tuple_list->u_tuple_list.len; i++) {
750 const char *s2 = qstr_str(((py_obj_base_t*)tuple_list->u_tuple_list.items[i])->u_str);
751 if (i > 0) {
752 strcat(joined_str, qstr_str(self->u_str));
753 }
754 strcat(joined_str, s2);
755 }
756 return py_obj_new_str(qstr_from_str_take(joined_str));
757
758bad_arg:
759 nlr_jump(py_obj_new_exception_2(q_TypeError, "?str.join expecting a list of str's", NULL, NULL));
760}
761
Damien2f06c572013-11-03 18:20:56 +0000762py_obj_t rt_str_format(int n_args, const py_obj_t* args) {
763 assert(IS_O(args[0], O_STR));
764 py_obj_base_t *self = args[0];
765
766 const char *str = qstr_str(self->u_str);
767 int arg_i = 1;
768 vstr_t *vstr = vstr_new();
769 for (; *str; str++) {
770 if (*str == '{') {
771 str++;
772 if (*str == '{') {
773 vstr_add_char(vstr, '{');
774 } else if (*str == '}') {
775 if (arg_i >= n_args) {
776 nlr_jump(py_obj_new_exception_2(q_IndexError, "tuple index out of range", NULL, NULL));
777 }
778 py_obj_print_helper(vstr_printf_wrapper, vstr, args[arg_i]);
779 arg_i++;
780 }
781 } else {
782 vstr_add_char(vstr, *str);
783 }
784 }
785
786 return py_obj_new_str(qstr_from_str_take(vstr->buf));
787}
788
Damienc226dca2013-10-16 16:12:52 +0100789py_obj_t rt_list_append(py_obj_t self_in, py_obj_t arg) {
Damien429d7192013-10-04 19:53:11 +0100790 assert(IS_O(self_in, O_LIST));
791 py_obj_base_t *self = self_in;
Damienc226dca2013-10-16 16:12:52 +0100792 if (self->u_tuple_list.len >= self->u_tuple_list.alloc) {
793 self->u_tuple_list.alloc *= 2;
794 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 +0100795 }
Damienc226dca2013-10-16 16:12:52 +0100796 self->u_tuple_list.items[self->u_tuple_list.len++] = arg;
Damienccfc9c52013-11-02 15:10:37 +0000797 return py_const_none; // return None, as per CPython
Damien429d7192013-10-04 19:53:11 +0100798}
799
Damienbd254452013-10-16 20:39:12 +0100800py_obj_t rt_gen_instance_next(py_obj_t self_in) {
801 py_obj_t ret = rt_iternext(self_in);
802 if (ret == py_const_stop_iteration) {
803 nlr_jump(py_obj_new_exception_0(qstr_from_str_static("StopIteration")));
804 } else {
805 return ret;
806 }
807}
808
Damien429d7192013-10-04 19:53:11 +0100809typedef enum {
Damien826005c2013-10-05 23:17:28 +0100810 PY_CODE_NONE,
Damien429d7192013-10-04 19:53:11 +0100811 PY_CODE_BYTE,
Damien826005c2013-10-05 23:17:28 +0100812 PY_CODE_NATIVE,
813 PY_CODE_INLINE_ASM,
Damien429d7192013-10-04 19:53:11 +0100814} py_code_kind_t;
815
816typedef struct _py_code_t {
817 py_code_kind_t kind;
818 int n_args;
Damienbd254452013-10-16 20:39:12 +0100819 int n_locals;
820 int n_stack;
821 bool is_generator;
Damien429d7192013-10-04 19:53:11 +0100822 union {
823 struct {
Damien429d7192013-10-04 19:53:11 +0100824 byte *code;
825 uint len;
826 } u_byte;
Damien826005c2013-10-05 23:17:28 +0100827 struct {
828 py_fun_t fun;
829 } u_native;
830 struct {
Damiene4af64f2013-10-06 12:04:13 +0100831 void *fun;
Damien826005c2013-10-05 23:17:28 +0100832 } u_inline_asm;
Damien429d7192013-10-04 19:53:11 +0100833 };
834} py_code_t;
835
836static int next_unique_code_id;
837static py_code_t *unique_codes;
838
Damien4ebb32f2013-11-02 14:33:10 +0000839py_obj_t fun_str_join;
Damien2f06c572013-11-03 18:20:56 +0000840py_obj_t fun_str_format;
Damien429d7192013-10-04 19:53:11 +0100841py_obj_t fun_list_append;
Damienbd254452013-10-16 20:39:12 +0100842py_obj_t fun_gen_instance_next;
Damien429d7192013-10-04 19:53:11 +0100843
Damien5ac1b2e2013-10-18 19:58:12 +0100844py_obj_t py_builtin___repl_print__(py_obj_t o) {
845 if (o != py_const_none) {
846 py_obj_print(o);
847 printf("\n");
848 }
849 return py_const_none;
850}
851
Damien5bf32c32013-11-06 17:16:35 +0000852py_obj_t py_builtin_print(int n_args, const py_obj_t* args) {
853 for (int i = 0; i < n_args; i++) {
854 if (i > 0) {
855 printf(" ");
856 }
857 if (IS_O(args[i], O_STR)) {
858 // special case, print string raw
859 printf("%s", qstr_str(((py_obj_base_t*)args[i])->u_str));
860 } else {
861 // print the object Python style
862 py_obj_print(args[i]);
863 }
Damien429d7192013-10-04 19:53:11 +0100864 }
Damien5bf32c32013-11-06 17:16:35 +0000865 printf("\n");
Damien429d7192013-10-04 19:53:11 +0100866 return py_const_none;
867}
868
869py_obj_t py_builtin_len(py_obj_t o_in) {
870 py_small_int_t len = 0;
Damien6b92d452013-11-09 20:13:55 +0000871 if (IS_O(o_in, O_STR)) {
872 py_obj_base_t *o = o_in;
873 len = strlen(qstr_str(o->u_str));
874 } else if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) {
Damien429d7192013-10-04 19:53:11 +0100875 py_obj_base_t *o = o_in;
Damienc226dca2013-10-16 16:12:52 +0100876 len = o->u_tuple_list.len;
Damien429d7192013-10-04 19:53:11 +0100877 } else if (IS_O(o_in, O_MAP)) {
878 py_obj_base_t *o = o_in;
879 len = o->u_map.used;
880 } else {
881 assert(0);
882 }
883 return TO_SMALL_INT(len);
884}
885
Damien7410e442013-11-02 19:47:57 +0000886py_obj_t py_builtin_abs(py_obj_t o_in) {
887 if (IS_SMALL_INT(o_in)) {
888 py_small_int_t val = FROM_SMALL_INT(o_in);
889 if (val < 0) {
890 val = -val;
891 }
892 return TO_SMALL_INT(val);
Damien6b92d452013-11-09 20:13:55 +0000893#if MICROPY_ENABLE_FLOAT
Damien7410e442013-11-02 19:47:57 +0000894 } else if (IS_O(o_in, O_FLOAT)) {
895 py_obj_base_t *o = o_in;
896 // TODO check for NaN etc
897 if (o->u_float < 0) {
898 return py_obj_new_float(-o->u_float);
899 } else {
900 return o_in;
901 }
902 } else if (IS_O(o_in, O_COMPLEX)) {
903 py_obj_base_t *o = o_in;
Damien6b92d452013-11-09 20:13:55 +0000904 return py_obj_new_float(machine_sqrt(o->u_complex.real*o->u_complex.real + o->u_complex.imag*o->u_complex.imag));
905#endif
Damien7410e442013-11-02 19:47:57 +0000906 } else {
907 assert(0);
908 return py_const_none;
909 }
910}
911
Damiena3977762013-10-09 23:10:10 +0100912py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name) {
913 // we differ from CPython: we set the new __locals__ object here
Damieneb19efb2013-10-10 22:06:54 +0100914 py_map_t *old_locals = map_locals;
Damiena3977762013-10-09 23:10:10 +0100915 py_map_t *class_locals = py_map_new(MAP_QSTR, 0);
Damieneb19efb2013-10-10 22:06:54 +0100916 map_locals = class_locals;
Damiena3977762013-10-09 23:10:10 +0100917
918 // call the class code
919 rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef);
920
921 // restore old __locals__ object
922 map_locals = old_locals;
923
924 // create and return the new class
Damien429d7192013-10-04 19:53:11 +0100925 py_obj_base_t *o = m_new(py_obj_base_t, 1);
926 o->kind = O_CLASS;
Damiena3977762013-10-09 23:10:10 +0100927 o->u_class.locals = class_locals;
Damien429d7192013-10-04 19:53:11 +0100928 return o;
929}
930
Damience89a212013-10-15 22:25:17 +0100931py_obj_t py_builtin_range(py_obj_t o_arg) {
Damien33af3bf2013-11-03 14:39:47 +0000932 return py_obj_new_range(0, py_obj_get_int(o_arg), 1);
Damience89a212013-10-15 22:25:17 +0100933}
934
Damien0446a0d2013-11-17 13:16:36 +0000935#ifdef WRITE_CODE
936FILE *fp_write_code = NULL;
Damiena1ddfcc2013-10-10 23:25:50 +0100937#endif
Damien429d7192013-10-04 19:53:11 +0100938
Damien8b3a7c22013-10-23 20:20:17 +0100939void rt_init(void) {
Damien429d7192013-10-04 19:53:11 +0100940 q_append = qstr_from_str_static("append");
Damien4ebb32f2013-11-02 14:33:10 +0000941 q_join = qstr_from_str_static("join");
Damien2f06c572013-11-03 18:20:56 +0000942 q_format = qstr_from_str_static("format");
Damien429d7192013-10-04 19:53:11 +0100943 q___build_class__ = qstr_from_str_static("__build_class__");
Damienbd254452013-10-16 20:39:12 +0100944 q___next__ = qstr_from_str_static("__next__");
Damience89a212013-10-15 22:25:17 +0100945 q_AttributeError = qstr_from_str_static("AttributeError");
Damienc226dca2013-10-16 16:12:52 +0100946 q_IndexError = qstr_from_str_static("IndexError");
Damien5ac1b2e2013-10-18 19:58:12 +0100947 q_KeyError = qstr_from_str_static("KeyError");
Damience89a212013-10-15 22:25:17 +0100948 q_NameError = qstr_from_str_static("NameError");
949 q_TypeError = qstr_from_str_static("TypeError");
Damien7410e442013-11-02 19:47:57 +0000950 q_SyntaxError = qstr_from_str_static("SyntaxError");
Damien429d7192013-10-04 19:53:11 +0100951
952 py_const_none = py_obj_new_const("None");
953 py_const_false = py_obj_new_const("False");
954 py_const_true = py_obj_new_const("True");
Damience89a212013-10-15 22:25:17 +0100955 py_const_stop_iteration = py_obj_new_const("StopIteration");
Damien429d7192013-10-04 19:53:11 +0100956
Damieneb19efb2013-10-10 22:06:54 +0100957 // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
958 map_locals = map_globals = py_map_new(MAP_QSTR, 1);
959 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 +0100960
961 py_map_init(&map_builtins, MAP_QSTR, 3);
Damien5ac1b2e2013-10-18 19:58:12 +0100962 py_qstr_map_lookup(&map_builtins, qstr_from_str_static("__repl_print__"), true)->value = rt_make_function_1(py_builtin___repl_print__);
Damien5bf32c32013-11-06 17:16:35 +0000963 py_qstr_map_lookup(&map_builtins, qstr_from_str_static("print"), true)->value = rt_make_function_var(0, py_builtin_print);
Damien2f06c572013-11-03 18:20:56 +0000964 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 +0000965 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 +0100966 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 +0100967 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 +0100968
Damien5ac1b2e2013-10-18 19:58:12 +0100969 next_unique_code_id = 2; // 1 is reserved for the __main__ module scope
Damien429d7192013-10-04 19:53:11 +0100970 unique_codes = NULL;
971
Damien4ebb32f2013-11-02 14:33:10 +0000972 fun_str_join = rt_make_function_2(rt_str_join);
Damien2f06c572013-11-03 18:20:56 +0000973 fun_str_format = rt_make_function_var(1, rt_str_format);
Damienc226dca2013-10-16 16:12:52 +0100974 fun_list_append = rt_make_function_2(rt_list_append);
Damienbd254452013-10-16 20:39:12 +0100975 fun_gen_instance_next = rt_make_function_1(rt_gen_instance_next);
Damien429d7192013-10-04 19:53:11 +0100976
Damien0446a0d2013-11-17 13:16:36 +0000977#ifdef WRITE_CODE
978 fp_write_code = fopen("out-code", "wb");
Damiena1ddfcc2013-10-10 23:25:50 +0100979#endif
Damien429d7192013-10-04 19:53:11 +0100980}
981
Damien8b3a7c22013-10-23 20:20:17 +0100982void rt_deinit(void) {
Damien0446a0d2013-11-17 13:16:36 +0000983#ifdef WRITE_CODE
984 if (fp_write_code != NULL) {
985 fclose(fp_write_code);
Damien429d7192013-10-04 19:53:11 +0100986 }
Damiena1ddfcc2013-10-10 23:25:50 +0100987#endif
Damien429d7192013-10-04 19:53:11 +0100988}
989
Damien5ac1b2e2013-10-18 19:58:12 +0100990int rt_get_unique_code_id(bool is_main_module) {
991 if (is_main_module) {
992 return 1;
993 } else {
994 return next_unique_code_id++;
995 }
Damien429d7192013-10-04 19:53:11 +0100996}
997
Damien8b3a7c22013-10-23 20:20:17 +0100998static void alloc_unique_codes(void) {
Damien429d7192013-10-04 19:53:11 +0100999 if (unique_codes == NULL) {
Damiene0b18642013-11-02 16:41:24 +00001000 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 +01001001 for (int i = 0; i < next_unique_code_id; i++) {
1002 unique_codes[i].kind = PY_CODE_NONE;
1003 }
Damien429d7192013-10-04 19:53:11 +01001004 }
Damien826005c2013-10-05 23:17:28 +01001005}
1006
Damienbd254452013-10-16 20:39:12 +01001007void 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 +01001008 alloc_unique_codes();
1009
1010 assert(unique_code_id < next_unique_code_id);
1011 unique_codes[unique_code_id].kind = PY_CODE_BYTE;
1012 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +01001013 unique_codes[unique_code_id].n_locals = n_locals;
1014 unique_codes[unique_code_id].n_stack = n_stack;
1015 unique_codes[unique_code_id].is_generator = is_generator;
Damien826005c2013-10-05 23:17:28 +01001016 unique_codes[unique_code_id].u_byte.code = code;
1017 unique_codes[unique_code_id].u_byte.len = len;
1018
Damien0446a0d2013-11-17 13:16:36 +00001019 printf("byte code: %d bytes\n", len);
1020
1021#ifdef DEBUG_PRINT
Damien826005c2013-10-05 23:17:28 +01001022 DEBUG_printf("assign byte code: id=%d code=%p len=%u n_args=%d\n", unique_code_id, code, len, n_args);
Damien0446a0d2013-11-17 13:16:36 +00001023 for (int i = 0; i < 128 && i < len; i++) {
1024 if (i > 0 && i % 16 == 0) {
1025 DEBUG_printf("\n");
1026 }
1027 DEBUG_printf(" %02x", code[i]);
1028 }
1029 DEBUG_printf("\n");
1030 py_un_byte_code(code, len);
1031
1032#ifdef WRITE_CODE
1033 if (fp_write_code != NULL) {
1034 fwrite(code, len, 1, fp_write_code);
1035 fflush(fp_write_code);
1036 }
1037#endif
1038#endif
Damien826005c2013-10-05 23:17:28 +01001039}
1040
1041void rt_assign_native_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
1042 alloc_unique_codes();
1043
Damienb05d7072013-10-05 13:37:10 +01001044 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
Damien429d7192013-10-04 19:53:11 +01001045 unique_codes[unique_code_id].kind = PY_CODE_NATIVE;
1046 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +01001047 unique_codes[unique_code_id].n_locals = 0;
1048 unique_codes[unique_code_id].n_stack = 0;
1049 unique_codes[unique_code_id].is_generator = false;
Damien429d7192013-10-04 19:53:11 +01001050 unique_codes[unique_code_id].u_native.fun = fun;
1051
Damien0446a0d2013-11-17 13:16:36 +00001052 printf("native code: %d bytes\n", len);
1053
Damiena1ddfcc2013-10-10 23:25:50 +01001054#ifdef DEBUG_PRINT
Damien429d7192013-10-04 19:53:11 +01001055 DEBUG_printf("assign native code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
1056 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
1057 for (int i = 0; i < 128 && i < len; i++) {
1058 if (i > 0 && i % 16 == 0) {
1059 DEBUG_printf("\n");
1060 }
1061 DEBUG_printf(" %02x", fun_data[i]);
1062 }
1063 DEBUG_printf("\n");
1064
Damien0446a0d2013-11-17 13:16:36 +00001065#ifdef WRITE_CODE
1066 if (fp_write_code != NULL) {
1067 fwrite(fun_data, len, 1, fp_write_code);
1068 fflush(fp_write_code);
Damien429d7192013-10-04 19:53:11 +01001069 }
Damiena1ddfcc2013-10-10 23:25:50 +01001070#endif
1071#endif
Damien429d7192013-10-04 19:53:11 +01001072}
1073
Damien826005c2013-10-05 23:17:28 +01001074void rt_assign_inline_asm_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
1075 alloc_unique_codes();
Damien429d7192013-10-04 19:53:11 +01001076
Damien826005c2013-10-05 23:17:28 +01001077 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
1078 unique_codes[unique_code_id].kind = PY_CODE_INLINE_ASM;
1079 unique_codes[unique_code_id].n_args = n_args;
Damienbd254452013-10-16 20:39:12 +01001080 unique_codes[unique_code_id].n_locals = 0;
1081 unique_codes[unique_code_id].n_stack = 0;
1082 unique_codes[unique_code_id].is_generator = false;
Damien826005c2013-10-05 23:17:28 +01001083 unique_codes[unique_code_id].u_inline_asm.fun = fun;
1084
Damiena1ddfcc2013-10-10 23:25:50 +01001085#ifdef DEBUG_PRINT
Damien826005c2013-10-05 23:17:28 +01001086 DEBUG_printf("assign inline asm code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
1087 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
1088 for (int i = 0; i < 128 && i < len; i++) {
1089 if (i > 0 && i % 16 == 0) {
1090 DEBUG_printf("\n");
1091 }
1092 DEBUG_printf(" %02x", fun_data[i]);
1093 }
1094 DEBUG_printf("\n");
1095
Damien0446a0d2013-11-17 13:16:36 +00001096#ifdef WRITE_CODE
1097 if (fp_write_code != NULL) {
1098 fwrite(fun_data, len, 1, fp_write_code);
Damien826005c2013-10-05 23:17:28 +01001099 }
Damiena1ddfcc2013-10-10 23:25:50 +01001100#endif
1101#endif
Damien429d7192013-10-04 19:53:11 +01001102}
1103
Damiena3977762013-10-09 23:10:10 +01001104bool py_obj_is_callable(py_obj_t o_in) {
1105 if (IS_SMALL_INT(o_in)) {
1106 return false;
1107 } else {
1108 py_obj_base_t *o = o_in;
1109 switch (o->kind) {
1110 case O_FUN_0:
1111 case O_FUN_1:
1112 case O_FUN_2:
Damien2f06c572013-11-03 18:20:56 +00001113 case O_FUN_VAR:
Damiena3977762013-10-09 23:10:10 +01001114 case O_FUN_N:
1115 case O_FUN_BC:
1116 case O_FUN_ASM:
Damieneb19efb2013-10-10 22:06:54 +01001117 // what about O_CLASS, and an O_OBJ that has a __call__ method?
Damiena3977762013-10-09 23:10:10 +01001118 return true;
1119 default:
1120 return false;
1121 }
1122 }
1123}
1124
Damien429d7192013-10-04 19:53:11 +01001125void py_obj_print(py_obj_t o_in) {
Damien2f06c572013-11-03 18:20:56 +00001126 py_obj_print_helper(printf_wrapper, NULL, o_in);
Damien429d7192013-10-04 19:53:11 +01001127}
1128
Damien7410e442013-11-02 19:47:57 +00001129#define PARSE_DEC_IN_INTG (1)
1130#define PARSE_DEC_IN_FRAC (2)
1131#define PARSE_DEC_IN_EXP (3)
1132
1133py_obj_t rt_load_const_dec(qstr qstr) {
1134#if MICROPY_ENABLE_FLOAT
1135 DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
1136 const char *s = qstr_str(qstr);
1137 int in = PARSE_DEC_IN_INTG;
1138 py_float_t dec_val = 0;
1139 bool exp_neg = false;
1140 int exp_val = 0;
1141 int exp_extra = 0;
1142 bool imag = false;
1143 for (; *s; s++) {
1144 int dig = *s;
1145 if ('0' <= dig && dig <= '9') {
1146 dig -= '0';
1147 if (in == PARSE_DEC_IN_EXP) {
1148 exp_val = 10 * exp_val + dig;
1149 } else {
1150 dec_val = 10 * dec_val + dig;
1151 if (in == PARSE_DEC_IN_FRAC) {
1152 exp_extra -= 1;
1153 }
1154 }
1155 } else if (in == PARSE_DEC_IN_INTG && dig == '.') {
1156 in = PARSE_DEC_IN_FRAC;
1157 } else if (in != PARSE_DEC_IN_EXP && (dig == 'E' || dig == 'e')) {
1158 in = PARSE_DEC_IN_EXP;
1159 if (s[1] == '+') {
1160 s++;
1161 } else if (s[1] == '-') {
1162 s++;
1163 exp_neg = true;
1164 }
1165 } else if (dig == 'J' || dig == 'j') {
1166 s++;
1167 imag = true;
1168 break;
1169 } else {
1170 // unknown character
1171 break;
1172 }
1173 }
1174 if (*s != 0) {
1175 nlr_jump(py_obj_new_exception_2(q_SyntaxError, "invalid syntax for number", NULL, NULL));
1176 }
1177 if (exp_neg) {
1178 exp_val = -exp_val;
1179 }
1180 exp_val += exp_extra;
1181 for (; exp_val > 0; exp_val--) {
1182 dec_val *= 10;
1183 }
1184 for (; exp_val < 0; exp_val++) {
1185 dec_val *= 0.1;
1186 }
1187 if (imag) {
1188 return py_obj_new_complex(0, dec_val);
1189 } else {
1190 return py_obj_new_float(dec_val);
1191 }
1192#else
1193 nlr_jump(py_obj_new_exception_2(q_SyntaxError, "decimal numbers not supported", NULL, NULL));
1194#endif
1195}
1196
Damien429d7192013-10-04 19:53:11 +01001197py_obj_t rt_load_const_str(qstr qstr) {
1198 DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
1199 return py_obj_new_str(qstr);
1200}
1201
1202py_obj_t rt_load_name(qstr qstr) {
1203 // logic: search locals, globals, builtins
Damiena3977762013-10-09 23:10:10 +01001204 DEBUG_OP_printf("load name %s\n", qstr_str(qstr));
Damieneb19efb2013-10-10 22:06:54 +01001205 py_map_elem_t *elem = py_qstr_map_lookup(map_locals, qstr, false);
Damiena3977762013-10-09 23:10:10 +01001206 if (elem == NULL) {
Damieneb19efb2013-10-10 22:06:54 +01001207 elem = py_qstr_map_lookup(map_globals, qstr, false);
Damiena3977762013-10-09 23:10:10 +01001208 if (elem == NULL) {
1209 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
1210 if (elem == NULL) {
Damience89a212013-10-15 22:25:17 +01001211 nlr_jump(py_obj_new_exception_2(q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL));
Damiena3977762013-10-09 23:10:10 +01001212 }
1213 }
1214 }
1215 return elem->value;
1216}
1217
1218py_obj_t rt_load_global(qstr qstr) {
1219 // logic: search globals, builtins
1220 DEBUG_OP_printf("load global %s\n", qstr_str(qstr));
Damieneb19efb2013-10-10 22:06:54 +01001221 py_map_elem_t *elem = py_qstr_map_lookup(map_globals, qstr, false);
Damien429d7192013-10-04 19:53:11 +01001222 if (elem == NULL) {
1223 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
1224 if (elem == NULL) {
Damience89a212013-10-15 22:25:17 +01001225 nlr_jump(py_obj_new_exception_2(q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL));
Damien429d7192013-10-04 19:53:11 +01001226 }
1227 }
1228 return elem->value;
1229}
1230
Damien8b3a7c22013-10-23 20:20:17 +01001231py_obj_t rt_load_build_class(void) {
Damien429d7192013-10-04 19:53:11 +01001232 DEBUG_OP_printf("load_build_class\n");
1233 py_map_elem_t *elem = py_qstr_map_lookup(&map_builtins, q___build_class__, false);
1234 if (elem == NULL) {
1235 printf("name doesn't exist: __build_class__\n");
1236 assert(0);
1237 }
1238 return elem->value;
1239}
1240
1241void rt_store_name(qstr qstr, py_obj_t obj) {
Damiena3977762013-10-09 23:10:10 +01001242 DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qstr), obj);
Damieneb19efb2013-10-10 22:06:54 +01001243 py_qstr_map_lookup(map_locals, qstr, true)->value = obj;
Damiena3977762013-10-09 23:10:10 +01001244}
1245
1246void rt_store_global(qstr qstr, py_obj_t obj) {
1247 DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qstr), obj);
Damieneb19efb2013-10-10 22:06:54 +01001248 py_qstr_map_lookup(map_globals, qstr, true)->value = obj;
Damien429d7192013-10-04 19:53:11 +01001249}
1250
1251py_obj_t rt_unary_op(int op, py_obj_t arg) {
Damien7410e442013-11-02 19:47:57 +00001252 DEBUG_OP_printf("unary %d %p\n", op, arg);
1253 if (IS_SMALL_INT(arg)) {
1254 py_small_int_t val = FROM_SMALL_INT(arg);
1255 switch (op) {
1256 case RT_UNARY_OP_NOT: if (val != 0) { return py_const_true;} else { return py_const_false; }
1257 case RT_UNARY_OP_POSITIVE: break;
1258 case RT_UNARY_OP_NEGATIVE: val = -val; break;
1259 case RT_UNARY_OP_INVERT: val = ~val; break;
1260 default: assert(0); val = 0;
1261 }
1262 if (fit_small_int(val)) {
1263 return TO_SMALL_INT(val);
1264 }
1265#if MICROPY_ENABLE_FLOAT
1266 } else if (IS_O(arg, O_FLOAT)) {
1267 py_float_t val = py_obj_get_float(arg);
1268 switch (op) {
1269 case RT_UNARY_OP_NOT: if (val != 0) { return py_const_true;} else { return py_const_false; }
1270 case RT_UNARY_OP_POSITIVE: break;
1271 case RT_UNARY_OP_NEGATIVE: val = -val; break;
1272 case RT_UNARY_OP_INVERT: nlr_jump(py_obj_new_exception_2(q_TypeError, "bad operand type for unary ~: 'float'", NULL, NULL));
1273 default: assert(0); val = 0;
1274 }
1275 return py_obj_new_float(val);
1276#endif
1277 }
Damien429d7192013-10-04 19:53:11 +01001278 assert(0);
1279 return py_const_none;
1280}
1281
Damienc226dca2013-10-16 16:12:52 +01001282uint get_index(py_obj_base_t *base, py_obj_t index) {
1283 // assumes base is O_TUPLE or O_LIST
1284 // TODO False and True are considered 0 and 1 for indexing purposes
1285 int len = base->u_tuple_list.len;
1286 if (IS_SMALL_INT(index)) {
1287 int i = FROM_SMALL_INT(index);
1288 if (i < 0) {
1289 i += len;
1290 }
1291 if (i < 0 || i >= len) {
1292 nlr_jump(py_obj_new_exception_2(q_IndexError, "%s index out of range", py_obj_get_type_str(base), NULL));
1293 }
1294 return i;
1295 } else {
1296 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)));
1297 }
1298}
1299
Damien429d7192013-10-04 19:53:11 +01001300py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs) {
1301 DEBUG_OP_printf("binary %d %p %p\n", op, lhs, rhs);
1302 if (op == RT_BINARY_OP_SUBSCR) {
Damien6b92d452013-11-09 20:13:55 +00001303 if (IS_O(lhs, O_STR)) {
1304 // string access
1305 // XXX a hack!
1306 const char *str = qstr_str(((py_obj_base_t*)lhs)->u_str);
1307 return py_obj_new_int(str[FROM_SMALL_INT(rhs)]);
1308 } else if ((IS_O(lhs, O_TUPLE) || IS_O(lhs, O_LIST))) {
Damien5ac1b2e2013-10-18 19:58:12 +01001309 // tuple/list load
Damienc226dca2013-10-16 16:12:52 +01001310 uint index = get_index(lhs, rhs);
1311 return ((py_obj_base_t*)lhs)->u_tuple_list.items[index];
Damien5ac1b2e2013-10-18 19:58:12 +01001312 } else if (IS_O(lhs, O_MAP)) {
1313 // map load
1314 py_map_elem_t *elem = py_map_lookup(lhs, rhs, false);
1315 if (elem == NULL) {
1316 nlr_jump(py_obj_new_exception_2(q_KeyError, "<value>", NULL, NULL));
1317 } else {
1318 return elem->value;
1319 }
Damien429d7192013-10-04 19:53:11 +01001320 } else {
1321 assert(0);
1322 }
1323 } else if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
Damien4ebb32f2013-11-02 14:33:10 +00001324 py_small_int_t lhs_val = FROM_SMALL_INT(lhs);
1325 py_small_int_t rhs_val = FROM_SMALL_INT(rhs);
Damien429d7192013-10-04 19:53:11 +01001326 switch (op) {
Damien7b2d3f32013-10-22 16:53:02 +01001327 case RT_BINARY_OP_OR:
Damien7410e442013-11-02 19:47:57 +00001328 case RT_BINARY_OP_INPLACE_OR: lhs_val |= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001329 case RT_BINARY_OP_XOR:
Damien7410e442013-11-02 19:47:57 +00001330 case RT_BINARY_OP_INPLACE_XOR: lhs_val ^= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001331 case RT_BINARY_OP_AND:
Damien7410e442013-11-02 19:47:57 +00001332 case RT_BINARY_OP_INPLACE_AND: lhs_val &= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001333 case RT_BINARY_OP_LSHIFT:
Damien7410e442013-11-02 19:47:57 +00001334 case RT_BINARY_OP_INPLACE_LSHIFT: lhs_val <<= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001335 case RT_BINARY_OP_RSHIFT:
Damien7410e442013-11-02 19:47:57 +00001336 case RT_BINARY_OP_INPLACE_RSHIFT: lhs_val >>= rhs_val; break;
Damien429d7192013-10-04 19:53:11 +01001337 case RT_BINARY_OP_ADD:
Damien7410e442013-11-02 19:47:57 +00001338 case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
Damienbd254452013-10-16 20:39:12 +01001339 case RT_BINARY_OP_SUBTRACT:
Damien7410e442013-11-02 19:47:57 +00001340 case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001341 case RT_BINARY_OP_MULTIPLY:
Damien7410e442013-11-02 19:47:57 +00001342 case RT_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;
Damien7b2d3f32013-10-22 16:53:02 +01001343 case RT_BINARY_OP_FLOOR_DIVIDE:
Damien7410e442013-11-02 19:47:57 +00001344 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: lhs_val /= rhs_val; break;
Damien3ef4abb2013-10-12 16:53:13 +01001345#if MICROPY_ENABLE_FLOAT
Damien7b2d3f32013-10-22 16:53:02 +01001346 case RT_BINARY_OP_TRUE_DIVIDE:
Damien7410e442013-11-02 19:47:57 +00001347 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 +01001348#endif
Damien4ebb32f2013-11-02 14:33:10 +00001349 case RT_BINARY_OP_POWER:
1350 case RT_BINARY_OP_INPLACE_POWER:
1351 // TODO
1352 if (rhs_val == 2) {
Damien7410e442013-11-02 19:47:57 +00001353 lhs_val = lhs_val * lhs_val;
Damien4ebb32f2013-11-02 14:33:10 +00001354 break;
1355 }
Damien7410e442013-11-02 19:47:57 +00001356 default: printf("%d\n", op); assert(0);
Damien429d7192013-10-04 19:53:11 +01001357 }
Damien7410e442013-11-02 19:47:57 +00001358 if (fit_small_int(lhs_val)) {
1359 return TO_SMALL_INT(lhs_val);
Damien429d7192013-10-04 19:53:11 +01001360 }
Damien4ebb32f2013-11-02 14:33:10 +00001361#if MICROPY_ENABLE_FLOAT
Damien7410e442013-11-02 19:47:57 +00001362 } else if (IS_O(lhs, O_COMPLEX) || IS_O(rhs, O_COMPLEX)) {
1363 py_float_t lhs_real, lhs_imag, rhs_real, rhs_imag;
1364 py_obj_get_complex(lhs, &lhs_real, &lhs_imag);
1365 py_obj_get_complex(rhs, &rhs_real, &rhs_imag);
Damien4ebb32f2013-11-02 14:33:10 +00001366 switch (op) {
1367 case RT_BINARY_OP_ADD:
Damien7410e442013-11-02 19:47:57 +00001368 case RT_BINARY_OP_INPLACE_ADD:
1369 lhs_real += rhs_real;
1370 lhs_imag += rhs_imag;
1371 break;
Damien4ebb32f2013-11-02 14:33:10 +00001372 case RT_BINARY_OP_SUBTRACT:
Damien7410e442013-11-02 19:47:57 +00001373 case RT_BINARY_OP_INPLACE_SUBTRACT:
1374 lhs_real -= rhs_real;
1375 lhs_imag -= rhs_imag;
1376 break;
Damien4ebb32f2013-11-02 14:33:10 +00001377 case RT_BINARY_OP_MULTIPLY:
Damien7410e442013-11-02 19:47:57 +00001378 case RT_BINARY_OP_INPLACE_MULTIPLY:
1379 {
1380 py_float_t real = lhs_real * rhs_real - lhs_imag * rhs_imag;
1381 lhs_imag = lhs_real * rhs_imag + lhs_imag * rhs_real;
1382 lhs_real = real;
1383 break;
1384 }
1385 /* TODO floor(?) the value
1386 case RT_BINARY_OP_FLOOR_DIVIDE:
1387 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break;
1388 */
1389 /* TODO
1390 case RT_BINARY_OP_TRUE_DIVIDE:
1391 case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: val = lhs_val / rhs_val; break;
1392 */
1393 default: printf("%d\n", op); assert(0);
1394 }
1395 return py_obj_new_complex(lhs_real, lhs_imag);
1396 } else if (IS_O(lhs, O_FLOAT) || IS_O(rhs, O_FLOAT)) {
1397 py_float_t lhs_val = py_obj_get_float(lhs);
1398 py_float_t rhs_val = py_obj_get_float(rhs);
1399 switch (op) {
1400 case RT_BINARY_OP_ADD:
1401 case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
1402 case RT_BINARY_OP_SUBTRACT:
1403 case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
1404 case RT_BINARY_OP_MULTIPLY:
1405 case RT_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;
Damien4ebb32f2013-11-02 14:33:10 +00001406 /* TODO floor(?) the value
1407 case RT_BINARY_OP_FLOOR_DIVIDE:
1408 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break;
1409 */
1410 case RT_BINARY_OP_TRUE_DIVIDE:
Damien7410e442013-11-02 19:47:57 +00001411 case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: lhs_val /= rhs_val; break;
1412 default: printf("%d\n", op); assert(0);
Damien4ebb32f2013-11-02 14:33:10 +00001413 }
Damien7410e442013-11-02 19:47:57 +00001414 return py_obj_new_float(lhs_val);
Damien4ebb32f2013-11-02 14:33:10 +00001415#endif
Damien429d7192013-10-04 19:53:11 +01001416 } else if (IS_O(lhs, O_STR) && IS_O(rhs, O_STR)) {
1417 const char *lhs_str = qstr_str(((py_obj_base_t*)lhs)->u_str);
1418 const char *rhs_str = qstr_str(((py_obj_base_t*)rhs)->u_str);
1419 char *val;
1420 switch (op) {
1421 case RT_BINARY_OP_ADD:
1422 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;
1423 default: printf("%d\n", op); assert(0); val = NULL;
1424 }
1425 return py_obj_new_str(qstr_from_str_take(val));
1426 }
1427 assert(0);
1428 return py_const_none;
1429}
1430
1431py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs) {
1432 DEBUG_OP_printf("compare %d %p %p\n", op, lhs, rhs);
Damien7b2d3f32013-10-22 16:53:02 +01001433
1434 // deal with == and !=
1435 if (op == RT_COMPARE_OP_EQUAL || op == RT_COMPARE_OP_NOT_EQUAL) {
1436 if (py_obj_equal(lhs, rhs)) {
1437 if (op == RT_COMPARE_OP_EQUAL) {
1438 return py_const_true;
1439 } else {
1440 return py_const_false;
1441 }
1442 } else {
1443 if (op == RT_COMPARE_OP_EQUAL) {
1444 return py_const_false;
1445 } else {
1446 return py_const_true;
1447 }
1448 }
1449 }
1450
1451 // deal with small ints
Damien429d7192013-10-04 19:53:11 +01001452 if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
Damien4ebb32f2013-11-02 14:33:10 +00001453 py_small_int_t lhs_val = FROM_SMALL_INT(lhs);
1454 py_small_int_t rhs_val = FROM_SMALL_INT(rhs);
Damien429d7192013-10-04 19:53:11 +01001455 int cmp;
1456 switch (op) {
Damien4ebb32f2013-11-02 14:33:10 +00001457 case RT_COMPARE_OP_LESS: cmp = lhs_val < rhs_val; break;
1458 case RT_COMPARE_OP_MORE: cmp = lhs_val > rhs_val; break;
1459 case RT_COMPARE_OP_LESS_EQUAL: cmp = lhs_val <= rhs_val; break;
1460 case RT_COMPARE_OP_MORE_EQUAL: cmp = lhs_val >= rhs_val; break;
Damien429d7192013-10-04 19:53:11 +01001461 default: assert(0); cmp = 0;
1462 }
1463 if (cmp) {
1464 return py_const_true;
1465 } else {
1466 return py_const_false;
1467 }
1468 }
Damien7b2d3f32013-10-22 16:53:02 +01001469
Damien4ebb32f2013-11-02 14:33:10 +00001470#if MICROPY_ENABLE_FLOAT
1471 // deal with floats
1472 if (IS_O(lhs, O_FLOAT) || IS_O(rhs, O_FLOAT)) {
Damien7410e442013-11-02 19:47:57 +00001473 py_float_t lhs_val = py_obj_get_float(lhs);
1474 py_float_t rhs_val = py_obj_get_float(rhs);
Damien4ebb32f2013-11-02 14:33:10 +00001475 int cmp;
1476 switch (op) {
1477 case RT_COMPARE_OP_LESS: cmp = lhs_val < rhs_val; break;
1478 case RT_COMPARE_OP_MORE: cmp = lhs_val > rhs_val; break;
1479 case RT_COMPARE_OP_LESS_EQUAL: cmp = lhs_val <= rhs_val; break;
1480 case RT_COMPARE_OP_MORE_EQUAL: cmp = lhs_val >= rhs_val; break;
1481 default: assert(0); cmp = 0;
1482 }
1483 if (cmp) {
1484 return py_const_true;
1485 } else {
1486 return py_const_false;
1487 }
1488 }
1489#endif
1490
Damien7b2d3f32013-10-22 16:53:02 +01001491 // not implemented
Damien429d7192013-10-04 19:53:11 +01001492 assert(0);
1493 return py_const_none;
1494}
1495
1496py_obj_t rt_make_function_from_id(int unique_code_id) {
Damienb05d7072013-10-05 13:37:10 +01001497 DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id);
1498 if (unique_code_id < 1 || unique_code_id >= next_unique_code_id) {
Damien429d7192013-10-04 19:53:11 +01001499 // illegal code id
1500 return py_const_none;
1501 }
1502 py_code_t *c = &unique_codes[unique_code_id];
1503 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1504 switch (c->kind) {
Damien826005c2013-10-05 23:17:28 +01001505 case PY_CODE_BYTE:
1506 o->kind = O_FUN_BC;
1507 o->u_fun_bc.n_args = c->n_args;
Damien40fdfe32013-11-05 22:16:22 +00001508 o->u_fun_bc.n_state = c->n_locals + c->n_stack;
Damien826005c2013-10-05 23:17:28 +01001509 o->u_fun_bc.code = c->u_byte.code;
Damien826005c2013-10-05 23:17:28 +01001510 break;
Damien429d7192013-10-04 19:53:11 +01001511 case PY_CODE_NATIVE:
1512 switch (c->n_args) {
1513 case 0: o->kind = O_FUN_0; break;
1514 case 1: o->kind = O_FUN_1; break;
1515 case 2: o->kind = O_FUN_2; break;
1516 default: assert(0);
1517 }
1518 o->u_fun.fun = c->u_native.fun;
1519 break;
Damien826005c2013-10-05 23:17:28 +01001520 case PY_CODE_INLINE_ASM:
1521 o->kind = O_FUN_ASM;
1522 o->u_fun_asm.n_args = c->n_args;
1523 o->u_fun_asm.fun = c->u_inline_asm.fun;
Damien429d7192013-10-04 19:53:11 +01001524 break;
1525 default:
1526 assert(0);
1527 }
Damienbd254452013-10-16 20:39:12 +01001528
1529 // check for generator functions and if so wrap in generator object
1530 if (c->is_generator) {
1531 py_obj_base_t *o2 = m_new(py_obj_base_t, 1);
1532 o2->kind = O_GEN_WRAP;
1533 // we have at least 3 locals so the bc can write back fast[0,1,2] safely; should improve how this is done
1534 o2->u_gen_wrap.n_state = (c->n_locals < 3 ? 3 : c->n_locals) + c->n_stack;
1535 o2->u_gen_wrap.fun = o;
1536 o = o2;
1537 }
1538
Damien429d7192013-10-04 19:53:11 +01001539 return o;
1540}
1541
1542py_obj_t rt_make_function_0(py_fun_0_t fun) {
1543 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1544 o->kind = O_FUN_0;
1545 o->u_fun.fun = fun;
1546 return o;
1547}
1548
1549py_obj_t rt_make_function_1(py_fun_1_t fun) {
1550 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1551 o->kind = O_FUN_1;
1552 o->u_fun.fun = fun;
1553 return o;
1554}
1555
1556py_obj_t rt_make_function_2(py_fun_2_t fun) {
1557 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1558 o->kind = O_FUN_2;
1559 o->u_fun.fun = fun;
1560 return o;
1561}
1562
1563py_obj_t rt_make_function(int n_args, py_fun_t code) {
1564 // assumes code is a pointer to a py_fun_t (i think this is safe...)
1565 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1566 o->kind = O_FUN_N;
Damien429d7192013-10-04 19:53:11 +01001567 o->u_fun.n_args = n_args;
Damien826005c2013-10-05 23:17:28 +01001568 o->u_fun.fun = code;
Damien429d7192013-10-04 19:53:11 +01001569 return o;
1570}
1571
Damien2f06c572013-11-03 18:20:56 +00001572py_obj_t rt_make_function_var(int n_fixed_args, py_fun_var_t f) {
1573 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1574 o->kind = O_FUN_VAR;
1575 o->u_fun.n_args = n_fixed_args;
1576 o->u_fun.fun = f;
1577 return o;
1578}
1579
Damieneb19efb2013-10-10 22:06:54 +01001580py_obj_t rt_call_function_0(py_obj_t fun) {
1581 return rt_call_function_n(fun, 0, NULL);
1582}
1583
1584py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) {
1585 return rt_call_function_n(fun, 1, &arg);
1586}
1587
1588py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) {
1589 py_obj_t args[2];
1590 args[1] = arg1;
1591 args[0] = arg2;
1592 return rt_call_function_n(fun, 2, args);
1593}
1594
1595typedef machine_uint_t (*inline_asm_fun_0_t)();
1596typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t);
1597typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t);
1598typedef machine_uint_t (*inline_asm_fun_3_t)(machine_uint_t, machine_uint_t, machine_uint_t);
1599
Damiene4af64f2013-10-06 12:04:13 +01001600// convert a Python object to a sensible value for inline asm
1601machine_uint_t rt_convert_obj_for_inline_asm(py_obj_t obj) {
1602 // TODO for byte_array, pass pointer to the array
1603 if (IS_SMALL_INT(obj)) {
1604 return FROM_SMALL_INT(obj);
1605 } else if (obj == py_const_none) {
1606 return 0;
1607 } else if (obj == py_const_false) {
1608 return 0;
1609 } else if (obj == py_const_true) {
1610 return 1;
1611 } else {
1612 py_obj_base_t *o = obj;
1613 switch (o->kind) {
1614 case O_STR:
1615 // pointer to the string (it's probably constant though!)
1616 return (machine_uint_t)qstr_str(o->u_str);
1617
Damien3ef4abb2013-10-12 16:53:13 +01001618#if MICROPY_ENABLE_FLOAT
Damiene4af64f2013-10-06 12:04:13 +01001619 case O_FLOAT:
1620 // convert float to int (could also pass in float registers)
Damien7410e442013-11-02 19:47:57 +00001621 return (machine_int_t)o->u_float;
Damienc025ebb2013-10-12 14:30:21 +01001622#endif
Damiene4af64f2013-10-06 12:04:13 +01001623
Damienc226dca2013-10-16 16:12:52 +01001624 case O_TUPLE:
Damiene4af64f2013-10-06 12:04:13 +01001625 case O_LIST:
Damienc226dca2013-10-16 16:12:52 +01001626 // pointer to start of tuple/list (could pass length, but then could use len(x) for that)
1627 return (machine_uint_t)o->u_tuple_list.items;
Damiene4af64f2013-10-06 12:04:13 +01001628
1629 default:
1630 // just pass along a pointer to the object
1631 return (machine_uint_t)obj;
1632 }
1633 }
1634}
1635
1636// convert a return value from inline asm to a sensible Python object
1637py_obj_t rt_convert_val_from_inline_asm(machine_uint_t val) {
1638 return TO_SMALL_INT(val);
1639}
1640
Damieneb19efb2013-10-10 22:06:54 +01001641// args are in reverse order in the array
1642py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args) {
1643 int n_args_fun = 0;
Damien429d7192013-10-04 19:53:11 +01001644 if (IS_O(fun, O_FUN_0)) {
1645 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001646 if (n_args != 0) {
1647 n_args_fun = 0;
1648 goto bad_n_args;
1649 }
1650 DEBUG_OP_printf("calling native %p()\n", o->u_fun.fun);
Damien429d7192013-10-04 19:53:11 +01001651 return ((py_fun_0_t)o->u_fun.fun)();
Damieneb19efb2013-10-10 22:06:54 +01001652
1653 } else if (IS_O(fun, O_FUN_1)) {
1654 py_obj_base_t *o = fun;
1655 if (n_args != 1) {
1656 n_args_fun = 1;
1657 goto bad_n_args;
1658 }
1659 DEBUG_OP_printf("calling native %p(%p)\n", o->u_fun.fun, args[0]);
1660 return ((py_fun_1_t)o->u_fun.fun)(args[0]);
1661
1662 } else if (IS_O(fun, O_FUN_2)) {
1663 py_obj_base_t *o = fun;
1664 if (n_args != 2) {
1665 n_args_fun = 2;
1666 goto bad_n_args;
1667 }
1668 DEBUG_OP_printf("calling native %p(%p, %p)\n", o->u_fun.fun, args[1], args[0]);
1669 return ((py_fun_2_t)o->u_fun.fun)(args[1], args[0]);
1670
1671 // TODO O_FUN_N
1672
Damien2f06c572013-11-03 18:20:56 +00001673 } else if (IS_O(fun, O_FUN_VAR)) {
1674 py_obj_base_t *o = fun;
1675 if (n_args < o->u_fun.n_args) {
1676 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));
1677 }
Damien5bf32c32013-11-06 17:16:35 +00001678 // TODO 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
1679 py_obj_t *args_ordered = m_new(py_obj_t, n_args);
Damien2f06c572013-11-03 18:20:56 +00001680 for (int i = 0; i < n_args; i++) {
1681 args_ordered[i] = args[n_args - i - 1];
1682 }
1683 py_obj_t res = ((py_fun_var_t)o->u_fun.fun)(n_args, args_ordered);
1684 m_free(args_ordered);
1685 return res;
1686
Damien429d7192013-10-04 19:53:11 +01001687 } else if (IS_O(fun, O_FUN_BC)) {
1688 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001689 if (n_args != o->u_fun_bc.n_args) {
1690 n_args_fun = o->u_fun_bc.n_args;
1691 goto bad_n_args;
1692 }
1693 DEBUG_OP_printf("calling byte code %p(n_args=%d)\n", o->u_fun_bc.code, n_args);
Damien40fdfe32013-11-05 22:16:22 +00001694 return py_execute_byte_code(o->u_fun_bc.code, args, n_args, o->u_fun_bc.n_state);
Damieneb19efb2013-10-10 22:06:54 +01001695
Damiene4af64f2013-10-06 12:04:13 +01001696 } else if (IS_O(fun, O_FUN_ASM)) {
1697 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001698 if (n_args != o->u_fun_asm.n_args) {
1699 n_args_fun = o->u_fun_asm.n_args;
1700 goto bad_n_args;
1701 }
1702 DEBUG_OP_printf("calling inline asm %p(n_args=%d)\n", o->u_fun_asm.fun, n_args);
1703 machine_uint_t ret;
1704 if (n_args == 0) {
1705 ret = ((inline_asm_fun_0_t)o->u_fun_asm.fun)();
1706 } else if (n_args == 1) {
1707 ret = ((inline_asm_fun_1_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[0]));
1708 } else if (n_args == 2) {
1709 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]));
1710 } else if (n_args == 3) {
1711 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]));
1712 } else {
1713 assert(0);
1714 ret = 0;
1715 }
1716 return rt_convert_val_from_inline_asm(ret);
1717
Damienbd254452013-10-16 20:39:12 +01001718 } else if (IS_O(fun, O_GEN_WRAP)) {
1719 py_obj_base_t *o = fun;
1720 py_obj_base_t *o_fun = o->u_gen_wrap.fun;
1721 assert(o_fun->kind == O_FUN_BC); // TODO
1722 if (n_args != o_fun->u_fun_bc.n_args) {
1723 n_args_fun = o_fun->u_fun_bc.n_args;
1724 goto bad_n_args;
1725 }
1726 py_obj_t *state = m_new(py_obj_t, 1 + o->u_gen_wrap.n_state);
1727 // put function object at first slot in state (to keep u_gen_instance small)
1728 state[0] = o_fun;
1729 // init args
1730 for (int i = 0; i < n_args; i++) {
1731 state[1 + i] = args[n_args - 1 - i];
1732 }
1733 py_obj_base_t *o2 = m_new(py_obj_base_t, 1);
1734 o2->kind = O_GEN_INSTANCE;
1735 o2->u_gen_instance.state = state;
1736 o2->u_gen_instance.ip = o_fun->u_fun_bc.code;
1737 o2->u_gen_instance.sp = state + o->u_gen_wrap.n_state;
1738 return o2;
1739
Damiena3977762013-10-09 23:10:10 +01001740 } else if (IS_O(fun, O_BOUND_METH)) {
1741 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001742 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);
1743 if (n_args == 0) {
1744 return rt_call_function_n(o->u_bound_meth.meth, 1, &o->u_bound_meth.self);
1745 } else if (n_args == 1) {
1746 py_obj_t args2[2];
1747 args2[1] = o->u_bound_meth.self;
1748 args2[0] = args[0];
1749 return rt_call_function_n(o->u_bound_meth.meth, 2, args2);
1750 } else {
1751 // TODO not implemented
1752 assert(0);
1753 return py_const_none;
1754 //return rt_call_function_2(o->u_bound_meth.meth, n_args + 1, o->u_bound_meth.self + args);
1755 }
1756
Damiena3977762013-10-09 23:10:10 +01001757 } else if (IS_O(fun, O_CLASS)) {
1758 // instantiate an instance of a class
Damieneb19efb2013-10-10 22:06:54 +01001759 if (n_args != 0) {
1760 n_args_fun = 0;
1761 goto bad_n_args;
1762 }
Damiena3977762013-10-09 23:10:10 +01001763 DEBUG_OP_printf("instantiate object of class %p with no args\n", fun);
1764 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1765 o->kind = O_OBJ;
1766 o->u_obj.class = fun;
1767 o->u_obj.members = py_map_new(MAP_QSTR, 0);
1768 return o;
Damieneb19efb2013-10-10 22:06:54 +01001769
Damien429d7192013-10-04 19:53:11 +01001770 } else {
Damieneb19efb2013-10-10 22:06:54 +01001771 printf("fun %p %d\n", fun, ((py_obj_base_t*)fun)->kind);
Damien429d7192013-10-04 19:53:11 +01001772 assert(0);
1773 return py_const_none;
1774 }
Damien429d7192013-10-04 19:53:11 +01001775
Damieneb19efb2013-10-10 22:06:54 +01001776bad_n_args:
Damienbd254452013-10-16 20:39:12 +01001777 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 +01001778}
1779
Damiena3977762013-10-09 23:10:10 +01001780// args contains: arg(n_args-1) arg(n_args-2) ... arg(0) self/NULL fun
1781// if n_args==0 then there are only self/NULL and fun
1782py_obj_t rt_call_method_n(int n_args, const py_obj_t *args) {
Damien7f5dacf2013-10-10 11:24:39 +01001783 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 +01001784 return rt_call_function_n(args[n_args + 1], n_args + ((args[n_args] == NULL) ? 0 : 1), args);
1785}
1786
Damien429d7192013-10-04 19:53:11 +01001787// items are in reverse order
Damienc226dca2013-10-16 16:12:52 +01001788py_obj_t rt_build_tuple(int n_args, py_obj_t *items) {
1789 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1790 o->kind = O_TUPLE;
1791 o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args;
1792 o->u_tuple_list.len = n_args;
1793 o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc);
1794 for (int i = 0; i < n_args; i++) {
1795 o->u_tuple_list.items[i] = items[n_args - i - 1];
1796 }
1797 return o;
1798}
1799
1800// items are in reverse order
Damien429d7192013-10-04 19:53:11 +01001801py_obj_t rt_build_list(int n_args, py_obj_t *items) {
1802 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1803 o->kind = O_LIST;
Damienc226dca2013-10-16 16:12:52 +01001804 o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args;
1805 o->u_tuple_list.len = n_args;
1806 o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc);
Damien429d7192013-10-04 19:53:11 +01001807 for (int i = 0; i < n_args; i++) {
Damienc226dca2013-10-16 16:12:52 +01001808 o->u_tuple_list.items[i] = items[n_args - i - 1];
Damien429d7192013-10-04 19:53:11 +01001809 }
1810 return o;
1811}
1812
1813py_obj_t py_set_lookup(py_obj_t o_in, py_obj_t index, bool add_if_not_found) {
1814 assert(IS_O(o_in, O_SET));
1815 py_obj_base_t *o = o_in;
1816 int hash = py_obj_hash(index);
1817 int pos = hash % o->u_set.alloc;
1818 for (;;) {
1819 py_obj_t elem = o->u_set.table[pos];
1820 if (elem == NULL) {
1821 // not in table
1822 if (add_if_not_found) {
1823 if (o->u_set.used + 1 >= o->u_set.alloc) {
1824 // not enough room in table, rehash it
1825 int old_alloc = o->u_set.alloc;
1826 py_obj_t *old_table = o->u_set.table;
1827 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(o->u_set.alloc + 1);
1828 o->u_set.used = 0;
1829 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
1830 for (int i = 0; i < old_alloc; i++) {
1831 if (old_table[i] != NULL) {
1832 py_set_lookup(o, old_table[i], true);
1833 }
1834 }
1835 m_free(old_table);
1836 // restart the search for the new element
1837 pos = hash % o->u_set.alloc;
1838 } else {
1839 o->u_set.used += 1;
1840 o->u_set.table[pos] = index;
1841 return index;
1842 }
1843 } else {
1844 return NULL;
1845 }
1846 } else if (py_obj_equal(elem, index)) {
1847 // found it
1848 return elem;
1849 } else {
1850 // not yet found, keep searching in this table
1851 pos = (pos + 1) % o->u_set.alloc;
1852 }
1853 }
1854}
1855
1856py_obj_t rt_build_set(int n_args, py_obj_t *items) {
1857 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1858 o->kind = O_SET;
1859 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(n_args + 1);
1860 o->u_set.used = 0;
1861 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
1862 for (int i = 0; i < o->u_set.alloc; i++) {
1863 o->u_set.table[i] = NULL;
1864 }
1865 for (int i = 0; i < n_args; i++) {
1866 py_set_lookup(o, items[i], true);
1867 }
1868 return o;
1869}
1870
Damienc12aa462013-10-16 20:57:49 +01001871py_obj_t rt_store_set(py_obj_t set, py_obj_t item) {
1872 py_set_lookup(set, item, true);
1873 return set;
1874}
1875
Damien429d7192013-10-04 19:53:11 +01001876py_obj_t rt_build_map(int n_args) {
1877 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1878 o->kind = O_MAP;
1879 py_map_init(&o->u_map, MAP_PY_OBJ, n_args);
1880 return o;
1881}
1882
1883py_obj_t rt_store_map(py_obj_t map, py_obj_t key, py_obj_t value) {
1884 assert(IS_O(map, O_MAP)); // should always be
1885 py_map_lookup(map, key, true)->value = value;
1886 return map;
1887}
1888
Damiena3977762013-10-09 23:10:10 +01001889py_obj_t build_bound_method(py_obj_t self, py_obj_t meth) {
1890 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1891 o->kind = O_BOUND_METH;
1892 o->u_bound_meth.meth = meth;
1893 o->u_bound_meth.self = self;
1894 return o;
1895}
1896
1897py_obj_t rt_load_attr(py_obj_t base, qstr attr) {
1898 DEBUG_OP_printf("load attr %s\n", qstr_str(attr));
1899 if (IS_O(base, O_LIST) && attr == q_append) {
1900 return build_bound_method(base, fun_list_append);
1901 } else if (IS_O(base, O_CLASS)) {
1902 py_obj_base_t *o = base;
1903 py_map_elem_t *elem = py_qstr_map_lookup(o->u_class.locals, attr, false);
1904 if (elem == NULL) {
1905 goto no_attr;
1906 }
1907 return elem->value;
1908 } else if (IS_O(base, O_OBJ)) {
1909 // logic: look in obj members then class locals (TODO check this against CPython)
1910 py_obj_base_t *o = base;
1911 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false);
1912 if (elem != NULL) {
1913 // object member, always treated as a value
1914 return elem->value;
1915 }
1916 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1917 if (elem != NULL) {
1918 if (py_obj_is_callable(elem->value)) {
1919 // class member is callable so build a bound method
1920 return build_bound_method(base, elem->value);
1921 } else {
1922 // class member is a value, so just return that value
1923 return elem->value;
1924 }
1925 }
1926 goto no_attr;
1927 }
1928
1929no_attr:
Damience89a212013-10-15 22:25:17 +01001930 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 +01001931}
1932
1933void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest) {
1934 DEBUG_OP_printf("load method %s\n", qstr_str(attr));
Damien2f06c572013-11-03 18:20:56 +00001935 if (IS_O(base, O_STR)) {
1936 if (attr == q_join) {
1937 dest[1] = fun_str_join;
1938 dest[0] = base;
1939 return;
1940 } else if (attr == q_format) {
1941 dest[1] = fun_str_format;
1942 dest[0] = base;
1943 return;
1944 }
Damien4ebb32f2013-11-02 14:33:10 +00001945 } else if (IS_O(base, O_GEN_INSTANCE) && attr == q___next__) {
Damienbd254452013-10-16 20:39:12 +01001946 dest[1] = fun_gen_instance_next;
1947 dest[0] = base;
1948 return;
1949 } else if (IS_O(base, O_LIST) && attr == q_append) {
Damiena3977762013-10-09 23:10:10 +01001950 dest[1] = fun_list_append;
1951 dest[0] = base;
1952 return;
1953 } else if (IS_O(base, O_OBJ)) {
1954 // logic: look in obj members then class locals (TODO check this against CPython)
1955 py_obj_base_t *o = base;
1956 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false);
1957 if (elem != NULL) {
1958 // object member, always treated as a value
1959 dest[1] = elem->value;
1960 dest[0] = NULL;
1961 return;
1962 }
1963 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1964 if (elem != NULL) {
1965 if (py_obj_is_callable(elem->value)) {
1966 // class member is callable so build a bound method
1967 dest[1] = elem->value;
1968 dest[0] = base;
1969 return;
1970 } else {
1971 // class member is a value, so just return that value
1972 dest[1] = elem->value;
1973 dest[0] = NULL;
1974 return;
1975 }
1976 }
1977 goto no_attr;
Damiend57eba52013-11-02 23:58:14 +00001978 } else if (IS_O(base, O_USER)) {
1979 py_obj_base_t *o = base;
1980 const py_user_method_t *meth = &o->u_user.info->methods[0];
1981 for (; meth->name != NULL; meth++) {
1982 if (strcmp(meth->name, qstr_str(attr)) == 0) {
1983 if (meth->kind == 0) {
1984 dest[1] = rt_make_function_1(meth->fun);
1985 } else if (meth->kind == 1) {
1986 dest[1] = rt_make_function_2(meth->fun);
1987 } else {
1988 assert(0);
1989 }
1990 dest[0] = base;
1991 return;
1992 }
1993 }
Damiena3977762013-10-09 23:10:10 +01001994 }
1995
1996no_attr:
1997 dest[1] = rt_load_attr(base, attr);
1998 dest[0] = NULL;
1999}
2000
Damien5ac1b2e2013-10-18 19:58:12 +01002001void rt_store_attr(py_obj_t base, qstr attr, py_obj_t value) {
2002 DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value);
Damienec63cce2013-10-22 22:58:17 +01002003 if (IS_O(base, O_CLASS)) {
2004 // TODO CPython allows STORE_ATTR to a class, but is this the correct implementation?
2005 py_obj_base_t *o = base;
2006 py_qstr_map_lookup(o->u_class.locals, attr, true)->value = value;
2007 } else if (IS_O(base, O_OBJ)) {
Damiena3977762013-10-09 23:10:10 +01002008 // logic: look in class locals (no add) then obj members (add) (TODO check this against CPython)
2009 py_obj_base_t *o = base;
2010 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
2011 if (elem != NULL) {
Damien5ac1b2e2013-10-18 19:58:12 +01002012 elem->value = value;
Damiena3977762013-10-09 23:10:10 +01002013 } else {
Damienec63cce2013-10-22 22:58:17 +01002014 py_qstr_map_lookup(o->u_obj.members, attr, true)->value = value;
Damiena3977762013-10-09 23:10:10 +01002015 }
2016 } else {
2017 printf("?AttributeError: '%s' object has no attribute '%s'\n", py_obj_get_type_str(base), qstr_str(attr));
2018 assert(0);
2019 }
2020}
2021
Damien429d7192013-10-04 19:53:11 +01002022void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t value) {
Damien5ac1b2e2013-10-18 19:58:12 +01002023 DEBUG_OP_printf("store subscr %p[%p] <- %p\n", base, index, value);
Damienc226dca2013-10-16 16:12:52 +01002024 if (IS_O(base, O_LIST)) {
Damien429d7192013-10-04 19:53:11 +01002025 // list store
Damienc226dca2013-10-16 16:12:52 +01002026 uint i = get_index(base, index);
2027 ((py_obj_base_t*)base)->u_tuple_list.items[i] = value;
Damien429d7192013-10-04 19:53:11 +01002028 } else if (IS_O(base, O_MAP)) {
2029 // map store
2030 py_map_lookup(base, index, true)->value = value;
2031 } else {
2032 assert(0);
2033 }
2034}
2035
Damience89a212013-10-15 22:25:17 +01002036py_obj_t rt_getiter(py_obj_t o_in) {
Damienbd254452013-10-16 20:39:12 +01002037 if (IS_O(o_in, O_GEN_INSTANCE)) {
2038 return o_in;
2039 } else if (IS_O(o_in, O_RANGE)) {
Damience89a212013-10-15 22:25:17 +01002040 py_obj_base_t *o = o_in;
2041 return py_obj_new_range_iterator(o->u_range.start, o->u_range.stop, o->u_range.step);
Damienc226dca2013-10-16 16:12:52 +01002042 } else if (IS_O(o_in, O_TUPLE)) {
2043 return py_obj_new_tuple_iterator(o_in, 0);
2044 } else if (IS_O(o_in, O_LIST)) {
2045 return py_obj_new_list_iterator(o_in, 0);
Damience89a212013-10-15 22:25:17 +01002046 } else {
2047 nlr_jump(py_obj_new_exception_2(q_TypeError, "'%s' object is not iterable", py_obj_get_type_str(o_in), NULL));
2048 }
2049}
2050
2051py_obj_t rt_iternext(py_obj_t o_in) {
Damienbd254452013-10-16 20:39:12 +01002052 if (IS_O(o_in, O_GEN_INSTANCE)) {
2053 py_obj_base_t *self = o_in;
Damien03c9cfb2013-11-05 22:06:08 +00002054 //py_obj_base_t *fun = self->u_gen_instance.state[0];
2055 //assert(fun->kind == O_FUN_BC);
2056 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 +01002057 if (yield) {
2058 return *self->u_gen_instance.sp;
2059 } else {
2060 if (*self->u_gen_instance.sp == py_const_none) {
2061 return py_const_stop_iteration;
2062 } else {
2063 // TODO return StopIteration with value *self->u_gen_instance.sp
2064 return py_const_stop_iteration;
2065 }
2066 }
2067
2068 } else if (IS_O(o_in, O_RANGE_IT)) {
Damience89a212013-10-15 22:25:17 +01002069 py_obj_base_t *o = o_in;
2070 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)) {
2071 py_obj_t o_out = TO_SMALL_INT(o->u_range_it.cur);
2072 o->u_range_it.cur += o->u_range_it.step;
2073 return o_out;
2074 } else {
2075 return py_const_stop_iteration;
2076 }
Damienbd254452013-10-16 20:39:12 +01002077
Damienc226dca2013-10-16 16:12:52 +01002078 } else if (IS_O(o_in, O_TUPLE_IT) || IS_O(o_in, O_LIST_IT)) {
2079 py_obj_base_t *o = o_in;
2080 if (o->u_tuple_list_it.cur < o->u_tuple_list_it.obj->u_tuple_list.len) {
2081 py_obj_t o_out = o->u_tuple_list_it.obj->u_tuple_list.items[o->u_tuple_list_it.cur];
2082 o->u_tuple_list_it.cur += 1;
2083 return o_out;
2084 } else {
2085 return py_const_stop_iteration;
2086 }
Damienbd254452013-10-16 20:39:12 +01002087
Damience89a212013-10-15 22:25:17 +01002088 } else {
2089 nlr_jump(py_obj_new_exception_2(q_TypeError, "? '%s' object is not iterable", py_obj_get_type_str(o_in), NULL));
2090 }
2091}
2092
Damien6ba13142013-11-02 20:34:54 +00002093// these must correspond to the respective enum
Damiendf4b4f32013-10-19 18:28:01 +01002094void *const rt_fun_table[RT_F_NUMBER_OF] = {
Damien6ba13142013-11-02 20:34:54 +00002095 rt_load_const_dec,
Damien429d7192013-10-04 19:53:11 +01002096 rt_load_const_str,
2097 rt_load_name,
2098 rt_load_global,
Damien7f5dacf2013-10-10 11:24:39 +01002099 rt_load_build_class,
Damien429d7192013-10-04 19:53:11 +01002100 rt_load_attr,
2101 rt_load_method,
2102 rt_store_name,
Damien7f5dacf2013-10-10 11:24:39 +01002103 rt_store_attr,
Damien429d7192013-10-04 19:53:11 +01002104 rt_store_subscr,
2105 rt_is_true,
2106 rt_unary_op,
Damiend2755ec2013-10-16 23:58:48 +01002107 rt_build_tuple,
Damien429d7192013-10-04 19:53:11 +01002108 rt_build_list,
Damiend2755ec2013-10-16 23:58:48 +01002109 rt_list_append,
Damien429d7192013-10-04 19:53:11 +01002110 rt_build_map,
2111 rt_store_map,
2112 rt_build_set,
Damiend2755ec2013-10-16 23:58:48 +01002113 rt_store_set,
Damien429d7192013-10-04 19:53:11 +01002114 rt_make_function_from_id,
Damieneb19efb2013-10-10 22:06:54 +01002115 rt_call_function_n,
Damien7f5dacf2013-10-10 11:24:39 +01002116 rt_call_method_n,
Damien429d7192013-10-04 19:53:11 +01002117 rt_binary_op,
2118 rt_compare_op,
Damiend2755ec2013-10-16 23:58:48 +01002119 rt_getiter,
2120 rt_iternext,
Damien429d7192013-10-04 19:53:11 +01002121};
2122
2123/*
2124void rt_f_vector(rt_fun_kind_t fun_kind) {
2125 (rt_f_table[fun_kind])();
2126}
2127*/
Damienec63cce2013-10-22 22:58:17 +01002128
2129// temporary way of making C modules
2130// hack: use class to mimic a module
2131
Damien8b3a7c22013-10-23 20:20:17 +01002132py_obj_t py_module_new(void) {
Damienec63cce2013-10-22 22:58:17 +01002133 py_obj_base_t *o = m_new(py_obj_base_t, 1);
2134 o->kind = O_CLASS;
2135 o->u_class.locals = py_map_new(MAP_QSTR, 0);
2136 return o;
2137}