blob: e80791df3388d1ab1cd19c8c51f87de469846586 [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
3
Damien429d7192013-10-04 19:53:11 +01004#include <stdint.h>
5#include <stdlib.h>
6#include <stdio.h>
7#include <string.h>
8#include <assert.h>
9
Damience89a212013-10-15 22:25:17 +010010#include "nlr.h"
Damien429d7192013-10-04 19:53:11 +010011#include "misc.h"
Damienc025ebb2013-10-12 14:30:21 +010012#include "mpyconfig.h"
Damien429d7192013-10-04 19:53:11 +010013#include "runtime.h"
Damieneb19efb2013-10-10 22:06:54 +010014#include "bc.h"
Damien429d7192013-10-04 19:53:11 +010015
Damien7f5dacf2013-10-10 11:24:39 +010016#if 0 // print debugging info
Damiena1ddfcc2013-10-10 23:25:50 +010017#define DEBUG_PRINT (1)
18#define WRITE_NATIVE (1)
Damien7f5dacf2013-10-10 11:24:39 +010019#define DEBUG_printf(args...) printf(args)
20#define DEBUG_OP_printf(args...) printf(args)
21#else // don't print debugging info
Damiena3977762013-10-09 23:10:10 +010022#define DEBUG_printf(args...) (void)0
Damien429d7192013-10-04 19:53:11 +010023#define DEBUG_OP_printf(args...) (void)0
Damien7f5dacf2013-10-10 11:24:39 +010024#endif
Damien429d7192013-10-04 19:53:11 +010025
Damien429d7192013-10-04 19:53:11 +010026typedef machine_int_t py_small_int_t;
27
28#define IS_O(o, k) (((((py_small_int_t)(o)) & 1) == 0) && (((py_obj_base_t*)(o))->kind == (k)))
29#define IS_SMALL_INT(o) (((py_small_int_t)(o)) & 1)
30#define FROM_SMALL_INT(o) (((py_small_int_t)(o)) >> 1)
31#define TO_SMALL_INT(o) ((py_obj_t)(((o) << 1) | 1))
32
Damien3ef4abb2013-10-12 16:53:13 +010033#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +010034typedef machine_float_t float_t;
35#endif
36
37typedef enum {
38 O_CONST,
39 O_STR,
Damien3ef4abb2013-10-12 16:53:13 +010040#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +010041 O_FLOAT,
42#endif
Damience89a212013-10-15 22:25:17 +010043 O_EXCEPTION_0,
44 O_EXCEPTION_2,
45 O_RANGE,
46 O_RANGE_IT,
Damien429d7192013-10-04 19:53:11 +010047 O_FUN_0,
48 O_FUN_1,
49 O_FUN_2,
50 O_FUN_N,
51 O_FUN_BC,
Damien826005c2013-10-05 23:17:28 +010052 O_FUN_ASM,
Damien429d7192013-10-04 19:53:11 +010053 O_BOUND_METH,
Damienc226dca2013-10-16 16:12:52 +010054 O_TUPLE,
Damien429d7192013-10-04 19:53:11 +010055 O_LIST,
Damienc226dca2013-10-16 16:12:52 +010056 O_TUPLE_IT,
57 O_LIST_IT,
Damien429d7192013-10-04 19:53:11 +010058 O_SET,
59 O_MAP,
60 O_CLASS,
Damiena3977762013-10-09 23:10:10 +010061 O_OBJ,
Damien429d7192013-10-04 19:53:11 +010062} py_obj_kind_t;
63
64typedef enum {
65 MAP_QSTR,
66 MAP_PY_OBJ,
67} py_map_kind_t;
68
69typedef struct _py_map_elem_t {
70 py_obj_t key;
71 py_obj_t value;
72} py_map_elem_t;
73
74typedef struct _py_map_t {
Damiena3977762013-10-09 23:10:10 +010075 py_map_kind_t kind; // TODO merge this 1-bit field into alloc or used
Damien429d7192013-10-04 19:53:11 +010076 machine_uint_t alloc;
77 machine_uint_t used;
78 py_map_elem_t *table;
79} py_map_t;
80
Damiena3977762013-10-09 23:10:10 +010081typedef struct _py_obj_base_t py_obj_base_t;
82
83struct _py_obj_base_t {
Damien429d7192013-10-04 19:53:11 +010084 py_obj_kind_t kind;
85 union {
86 const char *id;
87 qstr u_str;
Damien3ef4abb2013-10-12 16:53:13 +010088#if MICROPY_ENABLE_FLOAT
Damiene4af64f2013-10-06 12:04:13 +010089 float_t u_flt;
Damien429d7192013-10-04 19:53:11 +010090#endif
Damience89a212013-10-15 22:25:17 +010091 struct { // for O_EXCEPTION_0
92 qstr id;
93 } u_exc0;
94 struct { // for O_EXCEPTION_2
95 // TODO reduce size or make generic object or something
96 qstr id;
97 const char *fmt;
98 const char *s1;
99 const char *s2;
100 } u_exc2;
101 struct { // for O_RANGE
102 // TODO make generic object or something
103 machine_int_t start;
104 machine_int_t stop;
105 machine_int_t step;
106 } u_range;
107 struct { // for O_RANGE_IT
108 // TODO make generic object or something
109 machine_int_t cur;
110 machine_int_t stop;
111 machine_int_t step;
112 } u_range_it;
Damien429d7192013-10-04 19:53:11 +0100113 struct { // for O_FUN_[012N]
Damien429d7192013-10-04 19:53:11 +0100114 int n_args;
Damien826005c2013-10-05 23:17:28 +0100115 void *fun;
Damien429d7192013-10-04 19:53:11 +0100116 } u_fun;
117 struct { // for O_FUN_BC
Damien826005c2013-10-05 23:17:28 +0100118 int n_args;
Damien429d7192013-10-04 19:53:11 +0100119 byte *code;
120 uint len;
Damien429d7192013-10-04 19:53:11 +0100121 } u_fun_bc;
Damien826005c2013-10-05 23:17:28 +0100122 struct { // for O_FUN_ASM
123 int n_args;
124 void *fun;
125 } u_fun_asm;
Damien429d7192013-10-04 19:53:11 +0100126 struct { // for O_BOUND_METH
127 py_obj_t meth;
128 py_obj_t self;
129 } u_bound_meth;
Damienc226dca2013-10-16 16:12:52 +0100130 struct { // for O_TUPLE, O_LIST
Damien429d7192013-10-04 19:53:11 +0100131 int alloc;
132 int len;
133 py_obj_t *items;
Damienc226dca2013-10-16 16:12:52 +0100134 } u_tuple_list;
135 struct { // for O_TUPLE_IT, O_LIST_IT
136 py_obj_base_t *obj;
137 int cur;
138 } u_tuple_list_it;
Damien429d7192013-10-04 19:53:11 +0100139 struct { // for O_SET
140 int alloc;
141 int used;
142 py_obj_t *table;
143 } u_set;
144 py_map_t u_map; // for O_MAP
Damien429d7192013-10-04 19:53:11 +0100145 struct { // for O_CLASS
Damiena3977762013-10-09 23:10:10 +0100146 py_map_t *locals;
Damien429d7192013-10-04 19:53:11 +0100147 } u_class;
Damiena3977762013-10-09 23:10:10 +0100148 struct { // for O_OBJ
149 py_obj_base_t *class; // points to a O_CLASS object
150 py_map_t *members;
151 } u_obj;
Damien429d7192013-10-04 19:53:11 +0100152 };
Damiena3977762013-10-09 23:10:10 +0100153};
Damien429d7192013-10-04 19:53:11 +0100154
155py_obj_t py_const_none;
156py_obj_t py_const_false;
157py_obj_t py_const_true;
Damience89a212013-10-15 22:25:17 +0100158py_obj_t py_const_stop_iteration;
Damien429d7192013-10-04 19:53:11 +0100159
Damieneb19efb2013-10-10 22:06:54 +0100160// locals and globals need to be pointers because they can be the same in outer module scope
161py_map_t *map_locals;
162py_map_t *map_globals;
Damien429d7192013-10-04 19:53:11 +0100163py_map_t map_builtins;
164
165// approximatelly doubling primes; made with Mathematica command: Table[Prime[Floor[(1.7)^n]], {n, 3, 24}]
166static 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};
167
168int get_doubling_prime_greater_or_equal_to(int x) {
169 for (int i = 0; i < sizeof(doubling_primes) / sizeof(int); i++) {
170 if (doubling_primes[i] >= x) {
171 return doubling_primes[i];
172 }
173 }
174 // ran out of primes in the table!
175 // return something sensible, at least make it odd
176 return x | 1;
177}
178
179void py_map_init(py_map_t *map, py_map_kind_t kind, int n) {
180 map->kind = kind;
181 map->alloc = get_doubling_prime_greater_or_equal_to(n + 1);
182 map->used = 0;
183 map->table = m_new(py_map_elem_t, map->alloc);
184 for (int i = 0; i < map->alloc; i++) {
185 map->table[i].key = NULL;
186 map->table[i].value = NULL;
187 }
188}
189
190py_map_t *py_map_new(py_map_kind_t kind, int n) {
191 py_map_t *map = m_new(py_map_t, 1);
192 py_map_init(map, kind, n);
193 return map;
194}
195
196int py_obj_hash(py_obj_t o_in) {
197 if (IS_SMALL_INT(o_in)) {
198 return FROM_SMALL_INT(o_in);
199 } else if (IS_O(o_in, O_STR)) {
200 return ((py_obj_base_t*)o_in)->u_str;
201 } else {
202 assert(0);
203 return 0;
204 }
205}
206
207bool py_obj_equal(py_obj_t o1, py_obj_t o2) {
208 if (o1 == o2) {
209 return true;
210 } else if (IS_SMALL_INT(o1) && IS_SMALL_INT(o2)) {
211 return false;
212 } else if (IS_O(o1, O_STR) && IS_O(o2, O_STR)) {
213 return ((py_obj_base_t*)o1)->u_str == ((py_obj_base_t*)o2)->u_str;
214 } else {
215 assert(0);
216 return false;
217 }
218}
219
220py_map_elem_t* py_map_lookup_helper(py_map_t *map, py_obj_t index, bool add_if_not_found) {
221 bool is_map_py_obj = (map->kind == MAP_PY_OBJ);
222 machine_uint_t hash;
223 if (is_map_py_obj) {
224 hash = py_obj_hash(index);
225 } else {
226 hash = (machine_uint_t)index;
227 }
228 uint pos = hash % map->alloc;
229 for (;;) {
230 py_map_elem_t *elem = &map->table[pos];
231 if (elem->key == NULL) {
232 // not in table
233 if (add_if_not_found) {
234 if (map->used + 1 >= map->alloc) {
235 // not enough room in table, rehash it
236 int old_alloc = map->alloc;
237 py_map_elem_t *old_table = map->table;
238 map->alloc = get_doubling_prime_greater_or_equal_to(map->alloc + 1);
239 map->used = 0;
240 map->table = m_new(py_map_elem_t, map->alloc);
241 for (int i = 0; i < old_alloc; i++) {
242 if (old_table[i].key != NULL) {
243 py_map_lookup_helper(map, old_table[i].key, true)->value = old_table[i].value;
244 }
245 }
246 m_free(old_table);
247 // restart the search for the new element
248 pos = hash % map->alloc;
249 } else {
250 map->used += 1;
251 elem->key = index;
252 return elem;
253 }
254 } else {
255 return NULL;
256 }
257 } else if (elem->key == index || (is_map_py_obj && py_obj_equal(elem->key, index))) {
258 // found it
259 if (add_if_not_found) {
260 elem->key = index;
261 }
262 return elem;
263 } else {
264 // not yet found, keep searching in this table
265 pos = (pos + 1) % map->alloc;
266 }
267 }
268}
269
270py_map_elem_t* py_qstr_map_lookup(py_map_t *map, qstr index, bool add_if_not_found) {
271 py_obj_t o = (py_obj_t)(machine_uint_t)index;
272 return py_map_lookup_helper(map, o, add_if_not_found);
273}
274
275py_map_elem_t* py_map_lookup(py_obj_t o, py_obj_t index, bool add_if_not_found) {
276 assert(IS_O(o, O_MAP));
277 return py_map_lookup_helper(&((py_obj_base_t *)o)->u_map, index, add_if_not_found);
278}
279
280static bool fit_small_int(py_small_int_t o) {
281 return true;
282}
283
284py_obj_t py_obj_new_const(const char *id) {
285 py_obj_base_t *o = m_new(py_obj_base_t, 1);
286 o->kind = O_CONST;
287 o->id = id;
288 return (py_obj_t)o;
289}
290
291py_obj_t py_obj_new_str(qstr qstr) {
292 py_obj_base_t *o = m_new(py_obj_base_t, 1);
293 o->kind = O_STR;
294 o->u_str = qstr;
295 return (py_obj_t)o;
296}
297
Damien3ef4abb2013-10-12 16:53:13 +0100298#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100299py_obj_t py_obj_new_float(float_t val) {
300 py_obj_base_t *o = m_new(py_obj_base_t, 1);
301 o->kind = O_FLOAT;
Damiene4af64f2013-10-06 12:04:13 +0100302 o->u_flt = val;
Damien429d7192013-10-04 19:53:11 +0100303 return (py_obj_t)o;
304}
305#endif
306
Damience89a212013-10-15 22:25:17 +0100307py_obj_t py_obj_new_exception_0(qstr id) {
308 py_obj_base_t *o = m_new(py_obj_base_t, 1);
309 o->kind = O_EXCEPTION_0;
310 o->u_exc0.id = id;
311 return (py_obj_t)o;
312}
313
314py_obj_t py_obj_new_exception_2(qstr id, const char *fmt, const char *s1, const char *s2) {
315 py_obj_base_t *o = m_new(py_obj_base_t, 1);
316 o->kind = O_EXCEPTION_2;
317 o->u_exc2.id = id;
318 o->u_exc2.fmt = fmt;
319 o->u_exc2.s1 = s1;
320 o->u_exc2.s2 = s2;
321 return (py_obj_t)o;
322}
323
324// range is a class and instances are immutable sequence objects
325py_obj_t py_obj_new_range(int start, int stop, int step) {
326 py_obj_base_t *o = m_new(py_obj_base_t, 1);
327 o->kind = O_RANGE;
328 o->u_range.start = start;
329 o->u_range.stop = stop;
330 o->u_range.step = step;
331 return o;
332}
333
334py_obj_t py_obj_new_range_iterator(int cur, int stop, int step) {
335 py_obj_base_t *o = m_new(py_obj_base_t, 1);
336 o->kind = O_RANGE_IT;
337 o->u_range_it.cur = cur;
338 o->u_range_it.stop = stop;
339 o->u_range_it.step = step;
340 return o;
341}
342
Damienc226dca2013-10-16 16:12:52 +0100343py_obj_t py_obj_new_tuple_iterator(py_obj_base_t *tuple, int cur) {
344 py_obj_base_t *o = m_new(py_obj_base_t, 1);
345 o->kind = O_TUPLE_IT;
346 o->u_tuple_list_it.obj = tuple;
347 o->u_tuple_list_it.cur = cur;
348 return o;
349}
350
351py_obj_t py_obj_new_list_iterator(py_obj_base_t *list, int cur) {
352 py_obj_base_t *o = m_new(py_obj_base_t, 1);
353 o->kind = O_LIST_IT;
354 o->u_tuple_list_it.obj = list;
355 o->u_tuple_list_it.cur = cur;
356 return o;
357}
358
359py_obj_t rt_list_append(py_obj_t self_in, py_obj_t arg) {
Damien429d7192013-10-04 19:53:11 +0100360 assert(IS_O(self_in, O_LIST));
361 py_obj_base_t *self = self_in;
Damienc226dca2013-10-16 16:12:52 +0100362 if (self->u_tuple_list.len >= self->u_tuple_list.alloc) {
363 self->u_tuple_list.alloc *= 2;
364 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 +0100365 }
Damienc226dca2013-10-16 16:12:52 +0100366 self->u_tuple_list.items[self->u_tuple_list.len++] = arg;
Damien429d7192013-10-04 19:53:11 +0100367 return arg;
368}
369
370static qstr q_append;
371static qstr q_print;
372static qstr q_len;
373static qstr q___build_class__;
Damience89a212013-10-15 22:25:17 +0100374static qstr q_AttributeError;
Damienc226dca2013-10-16 16:12:52 +0100375static qstr q_IndexError;
Damience89a212013-10-15 22:25:17 +0100376static qstr q_NameError;
377static qstr q_TypeError;
Damien429d7192013-10-04 19:53:11 +0100378
379typedef enum {
Damien826005c2013-10-05 23:17:28 +0100380 PY_CODE_NONE,
Damien429d7192013-10-04 19:53:11 +0100381 PY_CODE_BYTE,
Damien826005c2013-10-05 23:17:28 +0100382 PY_CODE_NATIVE,
383 PY_CODE_INLINE_ASM,
Damien429d7192013-10-04 19:53:11 +0100384} py_code_kind_t;
385
386typedef struct _py_code_t {
387 py_code_kind_t kind;
388 int n_args;
389 union {
390 struct {
Damien429d7192013-10-04 19:53:11 +0100391 byte *code;
392 uint len;
393 } u_byte;
Damien826005c2013-10-05 23:17:28 +0100394 struct {
395 py_fun_t fun;
396 } u_native;
397 struct {
Damiene4af64f2013-10-06 12:04:13 +0100398 void *fun;
Damien826005c2013-10-05 23:17:28 +0100399 } u_inline_asm;
Damien429d7192013-10-04 19:53:11 +0100400 };
401} py_code_t;
402
403static int next_unique_code_id;
404static py_code_t *unique_codes;
405
406py_obj_t fun_list_append;
407
408py_obj_t py_builtin_print(py_obj_t o) {
409 if (IS_O(o, O_STR)) {
410 // special case, print string raw
411 printf("%s\n", qstr_str(((py_obj_base_t*)o)->u_str));
412 } else {
413 // print the object Python style
414 py_obj_print(o);
415 printf("\n");
416 }
417 return py_const_none;
418}
419
420py_obj_t py_builtin_len(py_obj_t o_in) {
421 py_small_int_t len = 0;
Damienc226dca2013-10-16 16:12:52 +0100422 if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) {
Damien429d7192013-10-04 19:53:11 +0100423 py_obj_base_t *o = o_in;
Damienc226dca2013-10-16 16:12:52 +0100424 len = o->u_tuple_list.len;
Damien429d7192013-10-04 19:53:11 +0100425 } else if (IS_O(o_in, O_MAP)) {
426 py_obj_base_t *o = o_in;
427 len = o->u_map.used;
428 } else {
429 assert(0);
430 }
431 return TO_SMALL_INT(len);
432}
433
Damiena3977762013-10-09 23:10:10 +0100434py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name) {
435 // we differ from CPython: we set the new __locals__ object here
Damieneb19efb2013-10-10 22:06:54 +0100436 py_map_t *old_locals = map_locals;
Damiena3977762013-10-09 23:10:10 +0100437 py_map_t *class_locals = py_map_new(MAP_QSTR, 0);
Damieneb19efb2013-10-10 22:06:54 +0100438 map_locals = class_locals;
Damiena3977762013-10-09 23:10:10 +0100439
440 // call the class code
441 rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef);
442
443 // restore old __locals__ object
444 map_locals = old_locals;
445
446 // create and return the new class
Damien429d7192013-10-04 19:53:11 +0100447 py_obj_base_t *o = m_new(py_obj_base_t, 1);
448 o->kind = O_CLASS;
Damiena3977762013-10-09 23:10:10 +0100449 o->u_class.locals = class_locals;
Damien429d7192013-10-04 19:53:11 +0100450 return o;
451}
452
Damience89a212013-10-15 22:25:17 +0100453py_obj_t py_builtin_range(py_obj_t o_arg) {
454 return py_obj_new_range(0, rt_get_int(o_arg), 1);
455}
456
Damiena1ddfcc2013-10-10 23:25:50 +0100457#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100458FILE *fp_native = NULL;
Damiena1ddfcc2013-10-10 23:25:50 +0100459#endif
Damien429d7192013-10-04 19:53:11 +0100460
461void rt_init() {
462 q_append = qstr_from_str_static("append");
463 q_print = qstr_from_str_static("print");
464 q_len = qstr_from_str_static("len");
465 q___build_class__ = qstr_from_str_static("__build_class__");
Damience89a212013-10-15 22:25:17 +0100466 q_AttributeError = qstr_from_str_static("AttributeError");
Damienc226dca2013-10-16 16:12:52 +0100467 q_IndexError = qstr_from_str_static("IndexError");
Damience89a212013-10-15 22:25:17 +0100468 q_NameError = qstr_from_str_static("NameError");
469 q_TypeError = qstr_from_str_static("TypeError");
Damien429d7192013-10-04 19:53:11 +0100470
471 py_const_none = py_obj_new_const("None");
472 py_const_false = py_obj_new_const("False");
473 py_const_true = py_obj_new_const("True");
Damience89a212013-10-15 22:25:17 +0100474 py_const_stop_iteration = py_obj_new_const("StopIteration");
Damien429d7192013-10-04 19:53:11 +0100475
Damieneb19efb2013-10-10 22:06:54 +0100476 // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
477 map_locals = map_globals = py_map_new(MAP_QSTR, 1);
478 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 +0100479
480 py_map_init(&map_builtins, MAP_QSTR, 3);
481 py_qstr_map_lookup(&map_builtins, q_print, true)->value = rt_make_function_1(py_builtin_print);
482 py_qstr_map_lookup(&map_builtins, q_len, true)->value = rt_make_function_1(py_builtin_len);
483 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 +0100484 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 +0100485
486 next_unique_code_id = 1;
487 unique_codes = NULL;
488
Damienc226dca2013-10-16 16:12:52 +0100489 fun_list_append = rt_make_function_2(rt_list_append);
Damien429d7192013-10-04 19:53:11 +0100490
Damiena1ddfcc2013-10-10 23:25:50 +0100491#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100492 fp_native = fopen("out-native", "wb");
Damiena1ddfcc2013-10-10 23:25:50 +0100493#endif
Damien429d7192013-10-04 19:53:11 +0100494}
495
496void rt_deinit() {
Damiena1ddfcc2013-10-10 23:25:50 +0100497#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100498 if (fp_native != NULL) {
499 fclose(fp_native);
500 }
Damiena1ddfcc2013-10-10 23:25:50 +0100501#endif
Damien429d7192013-10-04 19:53:11 +0100502}
503
504int rt_get_new_unique_code_id() {
505 return next_unique_code_id++;
506}
507
Damien826005c2013-10-05 23:17:28 +0100508static void alloc_unique_codes() {
Damien429d7192013-10-04 19:53:11 +0100509 if (unique_codes == NULL) {
510 unique_codes = m_new(py_code_t, next_unique_code_id);
Damien826005c2013-10-05 23:17:28 +0100511 for (int i = 0; i < next_unique_code_id; i++) {
512 unique_codes[i].kind = PY_CODE_NONE;
513 }
Damien429d7192013-10-04 19:53:11 +0100514 }
Damien826005c2013-10-05 23:17:28 +0100515}
516
517void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args) {
518 alloc_unique_codes();
519
520 assert(unique_code_id < next_unique_code_id);
521 unique_codes[unique_code_id].kind = PY_CODE_BYTE;
522 unique_codes[unique_code_id].n_args = n_args;
523 unique_codes[unique_code_id].u_byte.code = code;
524 unique_codes[unique_code_id].u_byte.len = len;
525
526 DEBUG_printf("assign byte code: id=%d code=%p len=%u n_args=%d\n", unique_code_id, code, len, n_args);
527}
528
529void rt_assign_native_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
530 alloc_unique_codes();
531
Damienb05d7072013-10-05 13:37:10 +0100532 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
Damien429d7192013-10-04 19:53:11 +0100533 unique_codes[unique_code_id].kind = PY_CODE_NATIVE;
534 unique_codes[unique_code_id].n_args = n_args;
535 unique_codes[unique_code_id].u_native.fun = fun;
536
Damiena1ddfcc2013-10-10 23:25:50 +0100537#ifdef DEBUG_PRINT
Damien429d7192013-10-04 19:53:11 +0100538 DEBUG_printf("assign native code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
539 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
540 for (int i = 0; i < 128 && i < len; i++) {
541 if (i > 0 && i % 16 == 0) {
542 DEBUG_printf("\n");
543 }
544 DEBUG_printf(" %02x", fun_data[i]);
545 }
546 DEBUG_printf("\n");
547
Damiena1ddfcc2013-10-10 23:25:50 +0100548#ifdef WRITE_NATIVE
Damien429d7192013-10-04 19:53:11 +0100549 if (fp_native != NULL) {
550 fwrite(fun_data, len, 1, fp_native);
Damien13ed3a62013-10-08 09:05:10 +0100551 fflush(fp_native);
Damien429d7192013-10-04 19:53:11 +0100552 }
Damiena1ddfcc2013-10-10 23:25:50 +0100553#endif
554#endif
Damien429d7192013-10-04 19:53:11 +0100555}
556
Damien826005c2013-10-05 23:17:28 +0100557void rt_assign_inline_asm_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
558 alloc_unique_codes();
Damien429d7192013-10-04 19:53:11 +0100559
Damien826005c2013-10-05 23:17:28 +0100560 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
561 unique_codes[unique_code_id].kind = PY_CODE_INLINE_ASM;
562 unique_codes[unique_code_id].n_args = n_args;
563 unique_codes[unique_code_id].u_inline_asm.fun = fun;
564
Damiena1ddfcc2013-10-10 23:25:50 +0100565#ifdef DEBUG_PRINT
Damien826005c2013-10-05 23:17:28 +0100566 DEBUG_printf("assign inline asm code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
567 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
568 for (int i = 0; i < 128 && i < len; i++) {
569 if (i > 0 && i % 16 == 0) {
570 DEBUG_printf("\n");
571 }
572 DEBUG_printf(" %02x", fun_data[i]);
573 }
574 DEBUG_printf("\n");
575
Damiena1ddfcc2013-10-10 23:25:50 +0100576#ifdef WRITE_NATIVE
Damien826005c2013-10-05 23:17:28 +0100577 if (fp_native != NULL) {
578 fwrite(fun_data, len, 1, fp_native);
579 }
Damiena1ddfcc2013-10-10 23:25:50 +0100580#endif
581#endif
Damien429d7192013-10-04 19:53:11 +0100582}
583
Damiena3977762013-10-09 23:10:10 +0100584bool py_obj_is_callable(py_obj_t o_in) {
585 if (IS_SMALL_INT(o_in)) {
586 return false;
587 } else {
588 py_obj_base_t *o = o_in;
589 switch (o->kind) {
590 case O_FUN_0:
591 case O_FUN_1:
592 case O_FUN_2:
593 case O_FUN_N:
594 case O_FUN_BC:
595 case O_FUN_ASM:
Damieneb19efb2013-10-10 22:06:54 +0100596 // what about O_CLASS, and an O_OBJ that has a __call__ method?
Damiena3977762013-10-09 23:10:10 +0100597 return true;
598 default:
599 return false;
600 }
601 }
602}
603
Damien429d7192013-10-04 19:53:11 +0100604const char *py_obj_get_type_str(py_obj_t o_in) {
605 if (IS_SMALL_INT(o_in)) {
606 return "int";
607 } else {
608 py_obj_base_t *o = o_in;
609 switch (o->kind) {
610 case O_CONST:
611 if (o == py_const_none) {
612 return "NoneType";
613 } else {
614 return "bool";
615 }
616 case O_STR:
617 return "str";
Damien3ef4abb2013-10-12 16:53:13 +0100618#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100619 case O_FLOAT:
620 return "float";
621#endif
Damien6cdd3af2013-10-05 18:08:26 +0100622 case O_FUN_0:
623 case O_FUN_1:
624 case O_FUN_2:
625 case O_FUN_N:
626 case O_FUN_BC:
627 return "function";
Damienc226dca2013-10-16 16:12:52 +0100628 case O_TUPLE:
629 return "tuple";
Damien429d7192013-10-04 19:53:11 +0100630 case O_LIST:
631 return "list";
Damienc226dca2013-10-16 16:12:52 +0100632 case O_TUPLE_IT:
633 return "tuple_iterator";
634 case O_LIST_IT:
635 return "list_iterator";
Damien429d7192013-10-04 19:53:11 +0100636 case O_SET:
637 return "set";
638 case O_MAP:
639 return "dict";
Damiena3977762013-10-09 23:10:10 +0100640 case O_OBJ:
641 {
642 py_map_elem_t *qn = py_qstr_map_lookup(o->u_obj.class->u_class.locals, qstr_from_str_static("__qualname__"), false);
643 assert(qn != NULL);
644 assert(IS_O(qn->value, O_STR));
645 return qstr_str(((py_obj_base_t*)qn->value)->u_str);
646 }
Damien429d7192013-10-04 19:53:11 +0100647 default:
648 assert(0);
649 return "UnknownType";
650 }
651 }
652}
653
654void py_obj_print(py_obj_t o_in) {
655 if (IS_SMALL_INT(o_in)) {
656 printf("%d", (int)FROM_SMALL_INT(o_in));
657 } else {
658 py_obj_base_t *o = o_in;
659 switch (o->kind) {
660 case O_CONST:
661 printf("%s", o->id);
662 break;
663 case O_STR:
664 // TODO need to escape chars etc
665 printf("'%s'", qstr_str(o->u_str));
666 break;
Damien3ef4abb2013-10-12 16:53:13 +0100667#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100668 case O_FLOAT:
Damiene4af64f2013-10-06 12:04:13 +0100669 printf("%f", o->u_flt);
Damien429d7192013-10-04 19:53:11 +0100670 break;
671#endif
Damience89a212013-10-15 22:25:17 +0100672 case O_EXCEPTION_2:
673 printf("%s: ", qstr_str(o->u_exc2.id));
674 printf(o->u_exc2.fmt, o->u_exc2.s1, o->u_exc2.s2);
675 break;
Damienc226dca2013-10-16 16:12:52 +0100676 case O_TUPLE:
677 printf("(");
678 for (int i = 0; i < o->u_tuple_list.len; i++) {
Damien429d7192013-10-04 19:53:11 +0100679 if (i > 0) {
680 printf(", ");
681 }
Damienc226dca2013-10-16 16:12:52 +0100682 py_obj_print(o->u_tuple_list.items[i]);
683 }
684 if (o->u_tuple_list.len == 1) {
685 printf(",");
686 }
687 printf(")");
688 break;
689 case O_LIST:
690 printf("[");
691 for (int i = 0; i < o->u_tuple_list.len; i++) {
692 if (i > 0) {
693 printf(", ");
694 }
695 py_obj_print(o->u_tuple_list.items[i]);
Damien429d7192013-10-04 19:53:11 +0100696 }
697 printf("]");
698 break;
699 case O_SET:
700 {
701 bool first = true;
702 printf("{");
703 for (int i = 0; i < o->u_set.alloc; i++) {
704 if (o->u_set.table[i] != NULL) {
705 if (!first) {
706 printf(", ");
707 }
708 first = false;
709 py_obj_print(o->u_set.table[i]);
710 }
711 }
712 printf("}");
713 break;
714 }
715 case O_MAP:
716 {
717 bool first = true;
718 printf("{");
719 for (int i = 0; i < o->u_map.alloc; i++) {
720 if (o->u_map.table[i].key != NULL) {
721 if (!first) {
722 printf(", ");
723 }
724 first = false;
725 py_obj_print(o->u_map.table[i].key);
726 printf(": ");
727 py_obj_print(o->u_map.table[i].value);
728 }
729 }
730 printf("}");
731 break;
732 }
733 default:
Damiena3977762013-10-09 23:10:10 +0100734 printf("<? %d>", o->kind);
Damien429d7192013-10-04 19:53:11 +0100735 assert(0);
736 }
737 }
738}
739
740int rt_is_true(py_obj_t arg) {
741 DEBUG_OP_printf("is true %p\n", arg);
742 if (IS_SMALL_INT(arg)) {
743 if (FROM_SMALL_INT(arg) == 0) {
744 return 0;
745 } else {
746 return 1;
747 }
748 } else if (arg == py_const_none) {
749 return 0;
750 } else if (arg == py_const_false) {
751 return 0;
752 } else if (arg == py_const_true) {
753 return 1;
754 } else {
755 assert(0);
756 return 0;
757 }
758}
759
760int rt_get_int(py_obj_t arg) {
Damienc226dca2013-10-16 16:12:52 +0100761 if (arg == py_const_false) {
762 return 0;
763 } else if (arg == py_const_true) {
764 return 1;
765 } else if (IS_SMALL_INT(arg)) {
Damien429d7192013-10-04 19:53:11 +0100766 return FROM_SMALL_INT(arg);
767 } else {
768 assert(0);
769 return 0;
770 }
771}
772
773py_obj_t rt_load_const_str(qstr qstr) {
774 DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
775 return py_obj_new_str(qstr);
776}
777
778py_obj_t rt_load_name(qstr qstr) {
779 // logic: search locals, globals, builtins
Damiena3977762013-10-09 23:10:10 +0100780 DEBUG_OP_printf("load name %s\n", qstr_str(qstr));
Damieneb19efb2013-10-10 22:06:54 +0100781 py_map_elem_t *elem = py_qstr_map_lookup(map_locals, qstr, false);
Damiena3977762013-10-09 23:10:10 +0100782 if (elem == NULL) {
Damieneb19efb2013-10-10 22:06:54 +0100783 elem = py_qstr_map_lookup(map_globals, qstr, false);
Damiena3977762013-10-09 23:10:10 +0100784 if (elem == NULL) {
785 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
786 if (elem == NULL) {
Damience89a212013-10-15 22:25:17 +0100787 nlr_jump(py_obj_new_exception_2(q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL));
Damiena3977762013-10-09 23:10:10 +0100788 }
789 }
790 }
791 return elem->value;
792}
793
794py_obj_t rt_load_global(qstr qstr) {
795 // logic: search globals, builtins
796 DEBUG_OP_printf("load global %s\n", qstr_str(qstr));
Damieneb19efb2013-10-10 22:06:54 +0100797 py_map_elem_t *elem = py_qstr_map_lookup(map_globals, qstr, false);
Damien429d7192013-10-04 19:53:11 +0100798 if (elem == NULL) {
799 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
800 if (elem == NULL) {
Damience89a212013-10-15 22:25:17 +0100801 nlr_jump(py_obj_new_exception_2(q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL));
Damien429d7192013-10-04 19:53:11 +0100802 }
803 }
804 return elem->value;
805}
806
Damien429d7192013-10-04 19:53:11 +0100807py_obj_t rt_load_build_class() {
808 DEBUG_OP_printf("load_build_class\n");
809 py_map_elem_t *elem = py_qstr_map_lookup(&map_builtins, q___build_class__, false);
810 if (elem == NULL) {
811 printf("name doesn't exist: __build_class__\n");
812 assert(0);
813 }
814 return elem->value;
815}
816
817void rt_store_name(qstr qstr, py_obj_t obj) {
Damiena3977762013-10-09 23:10:10 +0100818 DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qstr), obj);
Damieneb19efb2013-10-10 22:06:54 +0100819 py_qstr_map_lookup(map_locals, qstr, true)->value = obj;
Damiena3977762013-10-09 23:10:10 +0100820}
821
822void rt_store_global(qstr qstr, py_obj_t obj) {
823 DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qstr), obj);
Damieneb19efb2013-10-10 22:06:54 +0100824 py_qstr_map_lookup(map_globals, qstr, true)->value = obj;
Damien429d7192013-10-04 19:53:11 +0100825}
826
827py_obj_t rt_unary_op(int op, py_obj_t arg) {
828 assert(0);
829 return py_const_none;
830}
831
Damienc226dca2013-10-16 16:12:52 +0100832uint get_index(py_obj_base_t *base, py_obj_t index) {
833 // assumes base is O_TUPLE or O_LIST
834 // TODO False and True are considered 0 and 1 for indexing purposes
835 int len = base->u_tuple_list.len;
836 if (IS_SMALL_INT(index)) {
837 int i = FROM_SMALL_INT(index);
838 if (i < 0) {
839 i += len;
840 }
841 if (i < 0 || i >= len) {
842 nlr_jump(py_obj_new_exception_2(q_IndexError, "%s index out of range", py_obj_get_type_str(base), NULL));
843 }
844 return i;
845 } else {
846 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)));
847 }
848}
849
Damien429d7192013-10-04 19:53:11 +0100850py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs) {
851 DEBUG_OP_printf("binary %d %p %p\n", op, lhs, rhs);
852 if (op == RT_BINARY_OP_SUBSCR) {
Damienc226dca2013-10-16 16:12:52 +0100853 if ((IS_O(lhs, O_TUPLE) || IS_O(lhs, O_LIST))) {
854 uint index = get_index(lhs, rhs);
855 return ((py_obj_base_t*)lhs)->u_tuple_list.items[index];
Damien429d7192013-10-04 19:53:11 +0100856 } else {
857 assert(0);
858 }
859 } else if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
860 py_small_int_t val;
861 switch (op) {
862 case RT_BINARY_OP_ADD:
863 case RT_BINARY_OP_INPLACE_ADD: val = FROM_SMALL_INT(lhs) + FROM_SMALL_INT(rhs); break;
864 case RT_BINARY_OP_SUBTRACT: val = FROM_SMALL_INT(lhs) - FROM_SMALL_INT(rhs); break;
865 case RT_BINARY_OP_MULTIPLY: val = FROM_SMALL_INT(lhs) * FROM_SMALL_INT(rhs); break;
866 case RT_BINARY_OP_FLOOR_DIVIDE: val = FROM_SMALL_INT(lhs) / FROM_SMALL_INT(rhs); break;
Damien3ef4abb2013-10-12 16:53:13 +0100867#if MICROPY_ENABLE_FLOAT
Damien429d7192013-10-04 19:53:11 +0100868 case RT_BINARY_OP_TRUE_DIVIDE: return py_obj_new_float((float_t)FROM_SMALL_INT(lhs) / (float_t)FROM_SMALL_INT(rhs));
869#endif
870 default: printf("%d\n", op); assert(0); val = 0;
871 }
872 if (fit_small_int(val)) {
873 return TO_SMALL_INT(val);
874 }
875 } else if (IS_O(lhs, O_STR) && IS_O(rhs, O_STR)) {
876 const char *lhs_str = qstr_str(((py_obj_base_t*)lhs)->u_str);
877 const char *rhs_str = qstr_str(((py_obj_base_t*)rhs)->u_str);
878 char *val;
879 switch (op) {
880 case RT_BINARY_OP_ADD:
881 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;
882 default: printf("%d\n", op); assert(0); val = NULL;
883 }
884 return py_obj_new_str(qstr_from_str_take(val));
885 }
886 assert(0);
887 return py_const_none;
888}
889
890py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs) {
891 DEBUG_OP_printf("compare %d %p %p\n", op, lhs, rhs);
892 if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
893 int cmp;
894 switch (op) {
895 case RT_COMPARE_OP_LESS: cmp = FROM_SMALL_INT(lhs) < FROM_SMALL_INT(rhs); break;
896 case RT_COMPARE_OP_MORE: cmp = FROM_SMALL_INT(lhs) > FROM_SMALL_INT(rhs); break;
897 default: assert(0); cmp = 0;
898 }
899 if (cmp) {
900 return py_const_true;
901 } else {
902 return py_const_false;
903 }
904 }
905 assert(0);
906 return py_const_none;
907}
908
909py_obj_t rt_make_function_from_id(int unique_code_id) {
Damienb05d7072013-10-05 13:37:10 +0100910 DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id);
911 if (unique_code_id < 1 || unique_code_id >= next_unique_code_id) {
Damien429d7192013-10-04 19:53:11 +0100912 // illegal code id
913 return py_const_none;
914 }
915 py_code_t *c = &unique_codes[unique_code_id];
916 py_obj_base_t *o = m_new(py_obj_base_t, 1);
917 switch (c->kind) {
Damien826005c2013-10-05 23:17:28 +0100918 case PY_CODE_BYTE:
919 o->kind = O_FUN_BC;
920 o->u_fun_bc.n_args = c->n_args;
921 o->u_fun_bc.code = c->u_byte.code;
922 o->u_fun_bc.len = c->u_byte.len;
923 break;
Damien429d7192013-10-04 19:53:11 +0100924 case PY_CODE_NATIVE:
925 switch (c->n_args) {
926 case 0: o->kind = O_FUN_0; break;
927 case 1: o->kind = O_FUN_1; break;
928 case 2: o->kind = O_FUN_2; break;
929 default: assert(0);
930 }
931 o->u_fun.fun = c->u_native.fun;
932 break;
Damien826005c2013-10-05 23:17:28 +0100933 case PY_CODE_INLINE_ASM:
934 o->kind = O_FUN_ASM;
935 o->u_fun_asm.n_args = c->n_args;
936 o->u_fun_asm.fun = c->u_inline_asm.fun;
Damien429d7192013-10-04 19:53:11 +0100937 break;
938 default:
939 assert(0);
940 }
941 return o;
942}
943
944py_obj_t rt_make_function_0(py_fun_0_t fun) {
945 py_obj_base_t *o = m_new(py_obj_base_t, 1);
946 o->kind = O_FUN_0;
947 o->u_fun.fun = fun;
948 return o;
949}
950
951py_obj_t rt_make_function_1(py_fun_1_t fun) {
952 py_obj_base_t *o = m_new(py_obj_base_t, 1);
953 o->kind = O_FUN_1;
954 o->u_fun.fun = fun;
955 return o;
956}
957
958py_obj_t rt_make_function_2(py_fun_2_t fun) {
959 py_obj_base_t *o = m_new(py_obj_base_t, 1);
960 o->kind = O_FUN_2;
961 o->u_fun.fun = fun;
962 return o;
963}
964
965py_obj_t rt_make_function(int n_args, py_fun_t code) {
966 // assumes code is a pointer to a py_fun_t (i think this is safe...)
967 py_obj_base_t *o = m_new(py_obj_base_t, 1);
968 o->kind = O_FUN_N;
Damien429d7192013-10-04 19:53:11 +0100969 o->u_fun.n_args = n_args;
Damien826005c2013-10-05 23:17:28 +0100970 o->u_fun.fun = code;
Damien429d7192013-10-04 19:53:11 +0100971 return o;
972}
973
Damieneb19efb2013-10-10 22:06:54 +0100974py_obj_t rt_call_function_0(py_obj_t fun) {
975 return rt_call_function_n(fun, 0, NULL);
976}
977
978py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) {
979 return rt_call_function_n(fun, 1, &arg);
980}
981
982py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) {
983 py_obj_t args[2];
984 args[1] = arg1;
985 args[0] = arg2;
986 return rt_call_function_n(fun, 2, args);
987}
988
989typedef machine_uint_t (*inline_asm_fun_0_t)();
990typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t);
991typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t);
992typedef machine_uint_t (*inline_asm_fun_3_t)(machine_uint_t, machine_uint_t, machine_uint_t);
993
Damiene4af64f2013-10-06 12:04:13 +0100994// convert a Python object to a sensible value for inline asm
995machine_uint_t rt_convert_obj_for_inline_asm(py_obj_t obj) {
996 // TODO for byte_array, pass pointer to the array
997 if (IS_SMALL_INT(obj)) {
998 return FROM_SMALL_INT(obj);
999 } else if (obj == py_const_none) {
1000 return 0;
1001 } else if (obj == py_const_false) {
1002 return 0;
1003 } else if (obj == py_const_true) {
1004 return 1;
1005 } else {
1006 py_obj_base_t *o = obj;
1007 switch (o->kind) {
1008 case O_STR:
1009 // pointer to the string (it's probably constant though!)
1010 return (machine_uint_t)qstr_str(o->u_str);
1011
Damien3ef4abb2013-10-12 16:53:13 +01001012#if MICROPY_ENABLE_FLOAT
Damiene4af64f2013-10-06 12:04:13 +01001013 case O_FLOAT:
1014 // convert float to int (could also pass in float registers)
1015 return (machine_int_t)o->u_flt;
Damienc025ebb2013-10-12 14:30:21 +01001016#endif
Damiene4af64f2013-10-06 12:04:13 +01001017
Damienc226dca2013-10-16 16:12:52 +01001018 case O_TUPLE:
Damiene4af64f2013-10-06 12:04:13 +01001019 case O_LIST:
Damienc226dca2013-10-16 16:12:52 +01001020 // pointer to start of tuple/list (could pass length, but then could use len(x) for that)
1021 return (machine_uint_t)o->u_tuple_list.items;
Damiene4af64f2013-10-06 12:04:13 +01001022
1023 default:
1024 // just pass along a pointer to the object
1025 return (machine_uint_t)obj;
1026 }
1027 }
1028}
1029
1030// convert a return value from inline asm to a sensible Python object
1031py_obj_t rt_convert_val_from_inline_asm(machine_uint_t val) {
1032 return TO_SMALL_INT(val);
1033}
1034
Damieneb19efb2013-10-10 22:06:54 +01001035// args are in reverse order in the array
1036py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args) {
1037 int n_args_fun = 0;
Damien429d7192013-10-04 19:53:11 +01001038 if (IS_O(fun, O_FUN_0)) {
1039 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001040 if (n_args != 0) {
1041 n_args_fun = 0;
1042 goto bad_n_args;
1043 }
1044 DEBUG_OP_printf("calling native %p()\n", o->u_fun.fun);
Damien429d7192013-10-04 19:53:11 +01001045 return ((py_fun_0_t)o->u_fun.fun)();
Damieneb19efb2013-10-10 22:06:54 +01001046
1047 } else if (IS_O(fun, O_FUN_1)) {
1048 py_obj_base_t *o = fun;
1049 if (n_args != 1) {
1050 n_args_fun = 1;
1051 goto bad_n_args;
1052 }
1053 DEBUG_OP_printf("calling native %p(%p)\n", o->u_fun.fun, args[0]);
1054 return ((py_fun_1_t)o->u_fun.fun)(args[0]);
1055
1056 } else if (IS_O(fun, O_FUN_2)) {
1057 py_obj_base_t *o = fun;
1058 if (n_args != 2) {
1059 n_args_fun = 2;
1060 goto bad_n_args;
1061 }
1062 DEBUG_OP_printf("calling native %p(%p, %p)\n", o->u_fun.fun, args[1], args[0]);
1063 return ((py_fun_2_t)o->u_fun.fun)(args[1], args[0]);
1064
1065 // TODO O_FUN_N
1066
Damien429d7192013-10-04 19:53:11 +01001067 } else if (IS_O(fun, O_FUN_BC)) {
1068 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001069 if (n_args != o->u_fun_bc.n_args) {
1070 n_args_fun = o->u_fun_bc.n_args;
1071 goto bad_n_args;
1072 }
1073 DEBUG_OP_printf("calling byte code %p(n_args=%d)\n", o->u_fun_bc.code, n_args);
1074 return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, args, n_args);
1075
Damiene4af64f2013-10-06 12:04:13 +01001076 } else if (IS_O(fun, O_FUN_ASM)) {
1077 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001078 if (n_args != o->u_fun_asm.n_args) {
1079 n_args_fun = o->u_fun_asm.n_args;
1080 goto bad_n_args;
1081 }
1082 DEBUG_OP_printf("calling inline asm %p(n_args=%d)\n", o->u_fun_asm.fun, n_args);
1083 machine_uint_t ret;
1084 if (n_args == 0) {
1085 ret = ((inline_asm_fun_0_t)o->u_fun_asm.fun)();
1086 } else if (n_args == 1) {
1087 ret = ((inline_asm_fun_1_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[0]));
1088 } else if (n_args == 2) {
1089 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]));
1090 } else if (n_args == 3) {
1091 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]));
1092 } else {
1093 assert(0);
1094 ret = 0;
1095 }
1096 return rt_convert_val_from_inline_asm(ret);
1097
Damiena3977762013-10-09 23:10:10 +01001098 } else if (IS_O(fun, O_BOUND_METH)) {
1099 py_obj_base_t *o = fun;
Damieneb19efb2013-10-10 22:06:54 +01001100 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);
1101 if (n_args == 0) {
1102 return rt_call_function_n(o->u_bound_meth.meth, 1, &o->u_bound_meth.self);
1103 } else if (n_args == 1) {
1104 py_obj_t args2[2];
1105 args2[1] = o->u_bound_meth.self;
1106 args2[0] = args[0];
1107 return rt_call_function_n(o->u_bound_meth.meth, 2, args2);
1108 } else {
1109 // TODO not implemented
1110 assert(0);
1111 return py_const_none;
1112 //return rt_call_function_2(o->u_bound_meth.meth, n_args + 1, o->u_bound_meth.self + args);
1113 }
1114
Damiena3977762013-10-09 23:10:10 +01001115 } else if (IS_O(fun, O_CLASS)) {
1116 // instantiate an instance of a class
Damieneb19efb2013-10-10 22:06:54 +01001117 if (n_args != 0) {
1118 n_args_fun = 0;
1119 goto bad_n_args;
1120 }
Damiena3977762013-10-09 23:10:10 +01001121 DEBUG_OP_printf("instantiate object of class %p with no args\n", fun);
1122 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1123 o->kind = O_OBJ;
1124 o->u_obj.class = fun;
1125 o->u_obj.members = py_map_new(MAP_QSTR, 0);
1126 return o;
Damieneb19efb2013-10-10 22:06:54 +01001127
Damien429d7192013-10-04 19:53:11 +01001128 } else {
Damieneb19efb2013-10-10 22:06:54 +01001129 printf("fun %p %d\n", fun, ((py_obj_base_t*)fun)->kind);
Damien429d7192013-10-04 19:53:11 +01001130 assert(0);
1131 return py_const_none;
1132 }
Damien429d7192013-10-04 19:53:11 +01001133
Damieneb19efb2013-10-10 22:06:54 +01001134bad_n_args:
1135 printf("TypeError: function takes %d positional arguments but %d were given\n", n_args_fun, n_args);
1136 assert(0);
1137 return py_const_none;
Damien429d7192013-10-04 19:53:11 +01001138}
1139
Damiena3977762013-10-09 23:10:10 +01001140// args contains: arg(n_args-1) arg(n_args-2) ... arg(0) self/NULL fun
1141// if n_args==0 then there are only self/NULL and fun
1142py_obj_t rt_call_method_n(int n_args, const py_obj_t *args) {
Damien7f5dacf2013-10-10 11:24:39 +01001143 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 +01001144 return rt_call_function_n(args[n_args + 1], n_args + ((args[n_args] == NULL) ? 0 : 1), args);
1145}
1146
Damien429d7192013-10-04 19:53:11 +01001147// items are in reverse order
Damienc226dca2013-10-16 16:12:52 +01001148py_obj_t rt_build_tuple(int n_args, py_obj_t *items) {
1149 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1150 o->kind = O_TUPLE;
1151 o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args;
1152 o->u_tuple_list.len = n_args;
1153 o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc);
1154 for (int i = 0; i < n_args; i++) {
1155 o->u_tuple_list.items[i] = items[n_args - i - 1];
1156 }
1157 return o;
1158}
1159
1160// items are in reverse order
Damien429d7192013-10-04 19:53:11 +01001161py_obj_t rt_build_list(int n_args, py_obj_t *items) {
1162 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1163 o->kind = O_LIST;
Damienc226dca2013-10-16 16:12:52 +01001164 o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args;
1165 o->u_tuple_list.len = n_args;
1166 o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc);
Damien429d7192013-10-04 19:53:11 +01001167 for (int i = 0; i < n_args; i++) {
Damienc226dca2013-10-16 16:12:52 +01001168 o->u_tuple_list.items[i] = items[n_args - i - 1];
Damien429d7192013-10-04 19:53:11 +01001169 }
1170 return o;
1171}
1172
1173py_obj_t py_set_lookup(py_obj_t o_in, py_obj_t index, bool add_if_not_found) {
1174 assert(IS_O(o_in, O_SET));
1175 py_obj_base_t *o = o_in;
1176 int hash = py_obj_hash(index);
1177 int pos = hash % o->u_set.alloc;
1178 for (;;) {
1179 py_obj_t elem = o->u_set.table[pos];
1180 if (elem == NULL) {
1181 // not in table
1182 if (add_if_not_found) {
1183 if (o->u_set.used + 1 >= o->u_set.alloc) {
1184 // not enough room in table, rehash it
1185 int old_alloc = o->u_set.alloc;
1186 py_obj_t *old_table = o->u_set.table;
1187 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(o->u_set.alloc + 1);
1188 o->u_set.used = 0;
1189 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
1190 for (int i = 0; i < old_alloc; i++) {
1191 if (old_table[i] != NULL) {
1192 py_set_lookup(o, old_table[i], true);
1193 }
1194 }
1195 m_free(old_table);
1196 // restart the search for the new element
1197 pos = hash % o->u_set.alloc;
1198 } else {
1199 o->u_set.used += 1;
1200 o->u_set.table[pos] = index;
1201 return index;
1202 }
1203 } else {
1204 return NULL;
1205 }
1206 } else if (py_obj_equal(elem, index)) {
1207 // found it
1208 return elem;
1209 } else {
1210 // not yet found, keep searching in this table
1211 pos = (pos + 1) % o->u_set.alloc;
1212 }
1213 }
1214}
1215
1216py_obj_t rt_build_set(int n_args, py_obj_t *items) {
1217 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1218 o->kind = O_SET;
1219 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(n_args + 1);
1220 o->u_set.used = 0;
1221 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
1222 for (int i = 0; i < o->u_set.alloc; i++) {
1223 o->u_set.table[i] = NULL;
1224 }
1225 for (int i = 0; i < n_args; i++) {
1226 py_set_lookup(o, items[i], true);
1227 }
1228 return o;
1229}
1230
1231py_obj_t rt_build_map(int n_args) {
1232 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1233 o->kind = O_MAP;
1234 py_map_init(&o->u_map, MAP_PY_OBJ, n_args);
1235 return o;
1236}
1237
1238py_obj_t rt_store_map(py_obj_t map, py_obj_t key, py_obj_t value) {
1239 assert(IS_O(map, O_MAP)); // should always be
1240 py_map_lookup(map, key, true)->value = value;
1241 return map;
1242}
1243
Damiena3977762013-10-09 23:10:10 +01001244py_obj_t build_bound_method(py_obj_t self, py_obj_t meth) {
1245 py_obj_base_t *o = m_new(py_obj_base_t, 1);
1246 o->kind = O_BOUND_METH;
1247 o->u_bound_meth.meth = meth;
1248 o->u_bound_meth.self = self;
1249 return o;
1250}
1251
1252py_obj_t rt_load_attr(py_obj_t base, qstr attr) {
1253 DEBUG_OP_printf("load attr %s\n", qstr_str(attr));
1254 if (IS_O(base, O_LIST) && attr == q_append) {
1255 return build_bound_method(base, fun_list_append);
1256 } else if (IS_O(base, O_CLASS)) {
1257 py_obj_base_t *o = base;
1258 py_map_elem_t *elem = py_qstr_map_lookup(o->u_class.locals, attr, false);
1259 if (elem == NULL) {
1260 goto no_attr;
1261 }
1262 return elem->value;
1263 } else if (IS_O(base, O_OBJ)) {
1264 // logic: look in obj members then class locals (TODO check this against CPython)
1265 py_obj_base_t *o = base;
1266 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false);
1267 if (elem != NULL) {
1268 // object member, always treated as a value
1269 return elem->value;
1270 }
1271 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1272 if (elem != NULL) {
1273 if (py_obj_is_callable(elem->value)) {
1274 // class member is callable so build a bound method
1275 return build_bound_method(base, elem->value);
1276 } else {
1277 // class member is a value, so just return that value
1278 return elem->value;
1279 }
1280 }
1281 goto no_attr;
1282 }
1283
1284no_attr:
Damience89a212013-10-15 22:25:17 +01001285 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 +01001286}
1287
1288void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest) {
1289 DEBUG_OP_printf("load method %s\n", qstr_str(attr));
1290 if (IS_O(base, O_LIST) && attr == q_append) {
1291 dest[1] = fun_list_append;
1292 dest[0] = base;
1293 return;
1294 } else if (IS_O(base, O_OBJ)) {
1295 // logic: look in obj members then class locals (TODO check this against CPython)
1296 py_obj_base_t *o = base;
1297 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false);
1298 if (elem != NULL) {
1299 // object member, always treated as a value
1300 dest[1] = elem->value;
1301 dest[0] = NULL;
1302 return;
1303 }
1304 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1305 if (elem != NULL) {
1306 if (py_obj_is_callable(elem->value)) {
1307 // class member is callable so build a bound method
1308 dest[1] = elem->value;
1309 dest[0] = base;
1310 return;
1311 } else {
1312 // class member is a value, so just return that value
1313 dest[1] = elem->value;
1314 dest[0] = NULL;
1315 return;
1316 }
1317 }
1318 goto no_attr;
1319 }
1320
1321no_attr:
1322 dest[1] = rt_load_attr(base, attr);
1323 dest[0] = NULL;
1324}
1325
1326void rt_store_attr(py_obj_t base, qstr attr, py_obj_t val) {
1327 DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), val);
1328 if (IS_O(base, O_OBJ)) {
1329 // logic: look in class locals (no add) then obj members (add) (TODO check this against CPython)
1330 py_obj_base_t *o = base;
1331 py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false);
1332 if (elem != NULL) {
1333 elem->value = val;
1334 } else {
1335 elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, true)->value = val;
1336 }
1337 } else {
1338 printf("?AttributeError: '%s' object has no attribute '%s'\n", py_obj_get_type_str(base), qstr_str(attr));
1339 assert(0);
1340 }
1341}
1342
Damien429d7192013-10-04 19:53:11 +01001343void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t value) {
Damienc226dca2013-10-16 16:12:52 +01001344 if (IS_O(base, O_LIST)) {
Damien429d7192013-10-04 19:53:11 +01001345 // list store
Damienc226dca2013-10-16 16:12:52 +01001346 uint i = get_index(base, index);
1347 ((py_obj_base_t*)base)->u_tuple_list.items[i] = value;
Damien429d7192013-10-04 19:53:11 +01001348 } else if (IS_O(base, O_MAP)) {
1349 // map store
1350 py_map_lookup(base, index, true)->value = value;
1351 } else {
1352 assert(0);
1353 }
1354}
1355
Damience89a212013-10-15 22:25:17 +01001356py_obj_t rt_getiter(py_obj_t o_in) {
1357 if (IS_O(o_in, O_RANGE)) {
1358 py_obj_base_t *o = o_in;
1359 return py_obj_new_range_iterator(o->u_range.start, o->u_range.stop, o->u_range.step);
Damienc226dca2013-10-16 16:12:52 +01001360 } else if (IS_O(o_in, O_TUPLE)) {
1361 return py_obj_new_tuple_iterator(o_in, 0);
1362 } else if (IS_O(o_in, O_LIST)) {
1363 return py_obj_new_list_iterator(o_in, 0);
Damience89a212013-10-15 22:25:17 +01001364 } else {
1365 nlr_jump(py_obj_new_exception_2(q_TypeError, "'%s' object is not iterable", py_obj_get_type_str(o_in), NULL));
1366 }
1367}
1368
1369py_obj_t rt_iternext(py_obj_t o_in) {
1370 if (IS_O(o_in, O_RANGE_IT)) {
1371 py_obj_base_t *o = o_in;
1372 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)) {
1373 py_obj_t o_out = TO_SMALL_INT(o->u_range_it.cur);
1374 o->u_range_it.cur += o->u_range_it.step;
1375 return o_out;
1376 } else {
1377 return py_const_stop_iteration;
1378 }
Damienc226dca2013-10-16 16:12:52 +01001379 } else if (IS_O(o_in, O_TUPLE_IT) || IS_O(o_in, O_LIST_IT)) {
1380 py_obj_base_t *o = o_in;
1381 if (o->u_tuple_list_it.cur < o->u_tuple_list_it.obj->u_tuple_list.len) {
1382 py_obj_t o_out = o->u_tuple_list_it.obj->u_tuple_list.items[o->u_tuple_list_it.cur];
1383 o->u_tuple_list_it.cur += 1;
1384 return o_out;
1385 } else {
1386 return py_const_stop_iteration;
1387 }
Damience89a212013-10-15 22:25:17 +01001388 } else {
1389 nlr_jump(py_obj_new_exception_2(q_TypeError, "? '%s' object is not iterable", py_obj_get_type_str(o_in), NULL));
1390 }
1391}
1392
Damien429d7192013-10-04 19:53:11 +01001393void *rt_fun_table[RT_F_NUMBER_OF] = {
1394 rt_load_const_str,
1395 rt_load_name,
1396 rt_load_global,
Damien7f5dacf2013-10-10 11:24:39 +01001397 rt_load_build_class,
Damien429d7192013-10-04 19:53:11 +01001398 rt_load_attr,
1399 rt_load_method,
1400 rt_store_name,
Damien7f5dacf2013-10-10 11:24:39 +01001401 rt_store_attr,
Damien429d7192013-10-04 19:53:11 +01001402 rt_store_subscr,
1403 rt_is_true,
1404 rt_unary_op,
1405 rt_build_list,
1406 rt_build_map,
1407 rt_store_map,
1408 rt_build_set,
1409 rt_make_function_from_id,
Damieneb19efb2013-10-10 22:06:54 +01001410 rt_call_function_n,
Damien7f5dacf2013-10-10 11:24:39 +01001411 rt_call_method_n,
Damien429d7192013-10-04 19:53:11 +01001412 rt_binary_op,
1413 rt_compare_op,
1414};
1415
1416/*
1417void rt_f_vector(rt_fun_kind_t fun_kind) {
1418 (rt_f_table[fun_kind])();
1419}
1420*/