blob: 26ecdc14fe63d96a59949a2a78f1f533d6322916 [file] [log] [blame]
Damien429d7192013-10-04 19:53:11 +01001#include <stdint.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <string.h>
5#include <assert.h>
6
7#include "misc.h"
8#include "machine.h"
9#include "runtime.h"
Damienb05d7072013-10-05 13:37:10 +010010#include "vm.h"
Damien429d7192013-10-04 19:53:11 +010011
Damien6cdd3af2013-10-05 18:08:26 +010012//#define DEBUG_printf(args...) (void)0
13#define DEBUG_printf(args...) printf(args)
Damien429d7192013-10-04 19:53:11 +010014
15#define DEBUG_OP_printf(args...) (void)0
16//#define DEBUG_OP_printf(args...) printf(args)
17
18// enable/disable float support with this definition
19#define PY_FLOAT (1)
20
21typedef machine_int_t py_small_int_t;
22
23#define IS_O(o, k) (((((py_small_int_t)(o)) & 1) == 0) && (((py_obj_base_t*)(o))->kind == (k)))
24#define IS_SMALL_INT(o) (((py_small_int_t)(o)) & 1)
25#define FROM_SMALL_INT(o) (((py_small_int_t)(o)) >> 1)
26#define TO_SMALL_INT(o) ((py_obj_t)(((o) << 1) | 1))
27
28#ifdef PY_FLOAT
29typedef machine_float_t float_t;
30#endif
31
32typedef enum {
33 O_CONST,
34 O_STR,
35#ifdef PY_FLOAT
36 O_FLOAT,
37#endif
38 O_FUN_0,
39 O_FUN_1,
40 O_FUN_2,
41 O_FUN_N,
42 O_FUN_BC,
43 O_BOUND_METH,
44 O_LIST,
45 O_SET,
46 O_MAP,
47 O_CLASS,
48} py_obj_kind_t;
49
50typedef enum {
51 MAP_QSTR,
52 MAP_PY_OBJ,
53} py_map_kind_t;
54
55typedef struct _py_map_elem_t {
56 py_obj_t key;
57 py_obj_t value;
58} py_map_elem_t;
59
60typedef struct _py_map_t {
61 py_map_kind_t kind;
62 machine_uint_t alloc;
63 machine_uint_t used;
64 py_map_elem_t *table;
65} py_map_t;
66
67typedef struct _py_obj_base_t {
68 py_obj_kind_t kind;
69 union {
70 const char *id;
71 qstr u_str;
72#ifdef PY_FLOAT
73 float_t flt;
74#endif
75 struct { // for O_FUN_[012N]
76 void *fun;
77 int n_args;
78 } u_fun;
79 struct { // for O_FUN_BC
80 byte *code;
81 uint len;
82 int n_args;
83 } u_fun_bc;
84 struct { // for O_BOUND_METH
85 py_obj_t meth;
86 py_obj_t self;
87 } u_bound_meth;
88 struct { // for O_LIST
89 int alloc;
90 int len;
91 py_obj_t *items;
92 } u_list;
93 struct { // for O_SET
94 int alloc;
95 int used;
96 py_obj_t *table;
97 } u_set;
98 py_map_t u_map; // for O_MAP
99 /*
100 struct { // for O_MAP
101 int alloc;
102 int used;
103 py_map_elem_t *table;
104 } u_map;
105 */
106 struct { // for O_CLASS
107 py_map_t *map;
108 } u_class;
109 };
110} py_obj_base_t;
111
112py_obj_t py_const_none;
113py_obj_t py_const_false;
114py_obj_t py_const_true;
115
116py_map_t map_name;
117py_map_t map_builtins;
118
119// approximatelly doubling primes; made with Mathematica command: Table[Prime[Floor[(1.7)^n]], {n, 3, 24}]
120static 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};
121
122int get_doubling_prime_greater_or_equal_to(int x) {
123 for (int i = 0; i < sizeof(doubling_primes) / sizeof(int); i++) {
124 if (doubling_primes[i] >= x) {
125 return doubling_primes[i];
126 }
127 }
128 // ran out of primes in the table!
129 // return something sensible, at least make it odd
130 return x | 1;
131}
132
133void py_map_init(py_map_t *map, py_map_kind_t kind, int n) {
134 map->kind = kind;
135 map->alloc = get_doubling_prime_greater_or_equal_to(n + 1);
136 map->used = 0;
137 map->table = m_new(py_map_elem_t, map->alloc);
138 for (int i = 0; i < map->alloc; i++) {
139 map->table[i].key = NULL;
140 map->table[i].value = NULL;
141 }
142}
143
144py_map_t *py_map_new(py_map_kind_t kind, int n) {
145 py_map_t *map = m_new(py_map_t, 1);
146 py_map_init(map, kind, n);
147 return map;
148}
149
150int py_obj_hash(py_obj_t o_in) {
151 if (IS_SMALL_INT(o_in)) {
152 return FROM_SMALL_INT(o_in);
153 } else if (IS_O(o_in, O_STR)) {
154 return ((py_obj_base_t*)o_in)->u_str;
155 } else {
156 assert(0);
157 return 0;
158 }
159}
160
161bool py_obj_equal(py_obj_t o1, py_obj_t o2) {
162 if (o1 == o2) {
163 return true;
164 } else if (IS_SMALL_INT(o1) && IS_SMALL_INT(o2)) {
165 return false;
166 } else if (IS_O(o1, O_STR) && IS_O(o2, O_STR)) {
167 return ((py_obj_base_t*)o1)->u_str == ((py_obj_base_t*)o2)->u_str;
168 } else {
169 assert(0);
170 return false;
171 }
172}
173
174py_map_elem_t* py_map_lookup_helper(py_map_t *map, py_obj_t index, bool add_if_not_found) {
175 bool is_map_py_obj = (map->kind == MAP_PY_OBJ);
176 machine_uint_t hash;
177 if (is_map_py_obj) {
178 hash = py_obj_hash(index);
179 } else {
180 hash = (machine_uint_t)index;
181 }
182 uint pos = hash % map->alloc;
183 for (;;) {
184 py_map_elem_t *elem = &map->table[pos];
185 if (elem->key == NULL) {
186 // not in table
187 if (add_if_not_found) {
188 if (map->used + 1 >= map->alloc) {
189 // not enough room in table, rehash it
190 int old_alloc = map->alloc;
191 py_map_elem_t *old_table = map->table;
192 map->alloc = get_doubling_prime_greater_or_equal_to(map->alloc + 1);
193 map->used = 0;
194 map->table = m_new(py_map_elem_t, map->alloc);
195 for (int i = 0; i < old_alloc; i++) {
196 if (old_table[i].key != NULL) {
197 py_map_lookup_helper(map, old_table[i].key, true)->value = old_table[i].value;
198 }
199 }
200 m_free(old_table);
201 // restart the search for the new element
202 pos = hash % map->alloc;
203 } else {
204 map->used += 1;
205 elem->key = index;
206 return elem;
207 }
208 } else {
209 return NULL;
210 }
211 } else if (elem->key == index || (is_map_py_obj && py_obj_equal(elem->key, index))) {
212 // found it
213 if (add_if_not_found) {
214 elem->key = index;
215 }
216 return elem;
217 } else {
218 // not yet found, keep searching in this table
219 pos = (pos + 1) % map->alloc;
220 }
221 }
222}
223
224py_map_elem_t* py_qstr_map_lookup(py_map_t *map, qstr index, bool add_if_not_found) {
225 py_obj_t o = (py_obj_t)(machine_uint_t)index;
226 return py_map_lookup_helper(map, o, add_if_not_found);
227}
228
229py_map_elem_t* py_map_lookup(py_obj_t o, py_obj_t index, bool add_if_not_found) {
230 assert(IS_O(o, O_MAP));
231 return py_map_lookup_helper(&((py_obj_base_t *)o)->u_map, index, add_if_not_found);
232}
233
234static bool fit_small_int(py_small_int_t o) {
235 return true;
236}
237
238py_obj_t py_obj_new_const(const char *id) {
239 py_obj_base_t *o = m_new(py_obj_base_t, 1);
240 o->kind = O_CONST;
241 o->id = id;
242 return (py_obj_t)o;
243}
244
245py_obj_t py_obj_new_str(qstr qstr) {
246 py_obj_base_t *o = m_new(py_obj_base_t, 1);
247 o->kind = O_STR;
248 o->u_str = qstr;
249 return (py_obj_t)o;
250}
251
252#ifdef PY_FLOAT
253py_obj_t py_obj_new_float(float_t val) {
254 py_obj_base_t *o = m_new(py_obj_base_t, 1);
255 o->kind = O_FLOAT;
256 o->flt = val;
257 return (py_obj_t)o;
258}
259#endif
260
261py_obj_t list_append(py_obj_t self_in, py_obj_t arg) {
262 assert(IS_O(self_in, O_LIST));
263 py_obj_base_t *self = self_in;
264 if (self->u_list.len >= self->u_list.alloc) {
265 self->u_list.alloc *= 2;
266 self->u_list.items = m_renew(py_obj_t, self->u_list.items, self->u_list.alloc);
267 }
268 self->u_list.items[self->u_list.len++] = arg;
269 return arg;
270}
271
272static qstr q_append;
273static qstr q_print;
274static qstr q_len;
275static qstr q___build_class__;
276
277typedef enum {
278 PY_CODE_NATIVE,
279 PY_CODE_BYTE,
280} py_code_kind_t;
281
282typedef struct _py_code_t {
283 py_code_kind_t kind;
284 int n_args;
285 union {
286 struct {
287 py_fun_t fun;
288 } u_native;
289 struct {
290 byte *code;
291 uint len;
292 } u_byte;
293 };
294} py_code_t;
295
296static int next_unique_code_id;
297static py_code_t *unique_codes;
298
299py_obj_t fun_list_append;
300
301py_obj_t py_builtin_print(py_obj_t o) {
302 if (IS_O(o, O_STR)) {
303 // special case, print string raw
304 printf("%s\n", qstr_str(((py_obj_base_t*)o)->u_str));
305 } else {
306 // print the object Python style
307 py_obj_print(o);
308 printf("\n");
309 }
310 return py_const_none;
311}
312
313py_obj_t py_builtin_len(py_obj_t o_in) {
314 py_small_int_t len = 0;
315 if (IS_O(o_in, O_LIST)) {
316 py_obj_base_t *o = o_in;
317 len = o->u_list.len;
318 } else if (IS_O(o_in, O_MAP)) {
319 py_obj_base_t *o = o_in;
320 len = o->u_map.used;
321 } else {
322 assert(0);
323 }
324 return TO_SMALL_INT(len);
325}
326
327py_obj_t py_builtin___build_class__(py_obj_t o1, py_obj_t o2) {
328 py_obj_base_t *o = m_new(py_obj_base_t, 1);
329 o->kind = O_CLASS;
330 o->u_class.map = py_map_new(MAP_QSTR, 0);
331 return o;
332}
333
334FILE *fp_native = NULL;
335
336void rt_init() {
337 q_append = qstr_from_str_static("append");
338 q_print = qstr_from_str_static("print");
339 q_len = qstr_from_str_static("len");
340 q___build_class__ = qstr_from_str_static("__build_class__");
341
342 py_const_none = py_obj_new_const("None");
343 py_const_false = py_obj_new_const("False");
344 py_const_true = py_obj_new_const("True");
345
346 py_map_init(&map_name, MAP_QSTR, 0);
347
348 py_map_init(&map_builtins, MAP_QSTR, 3);
349 py_qstr_map_lookup(&map_builtins, q_print, true)->value = rt_make_function_1(py_builtin_print);
350 py_qstr_map_lookup(&map_builtins, q_len, true)->value = rt_make_function_1(py_builtin_len);
351 py_qstr_map_lookup(&map_builtins, q___build_class__, true)->value = rt_make_function_2(py_builtin___build_class__);
352
353 next_unique_code_id = 1;
354 unique_codes = NULL;
355
356 fun_list_append = rt_make_function_2(list_append);
357
358 fp_native = fopen("out-native", "wb");
359}
360
361void rt_deinit() {
362 if (fp_native != NULL) {
363 fclose(fp_native);
364 }
365}
366
367int rt_get_new_unique_code_id() {
368 return next_unique_code_id++;
369}
370
371void rt_assign_native_code(int unique_code_id, py_fun_t fun, uint len, int n_args) {
372 if (unique_codes == NULL) {
373 unique_codes = m_new(py_code_t, next_unique_code_id);
374 }
Damienb05d7072013-10-05 13:37:10 +0100375 assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
Damien429d7192013-10-04 19:53:11 +0100376 unique_codes[unique_code_id].kind = PY_CODE_NATIVE;
377 unique_codes[unique_code_id].n_args = n_args;
378 unique_codes[unique_code_id].u_native.fun = fun;
379
380 DEBUG_printf("assign native code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
381 byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
382 for (int i = 0; i < 128 && i < len; i++) {
383 if (i > 0 && i % 16 == 0) {
384 DEBUG_printf("\n");
385 }
386 DEBUG_printf(" %02x", fun_data[i]);
387 }
388 DEBUG_printf("\n");
389
390 if (fp_native != NULL) {
391 fwrite(fun_data, len, 1, fp_native);
392 }
393}
394
395void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args) {
396 if (unique_codes == NULL) {
397 unique_codes = m_new(py_code_t, next_unique_code_id);
398 }
399 assert(unique_code_id < next_unique_code_id);
400 unique_codes[unique_code_id].kind = PY_CODE_BYTE;
401 unique_codes[unique_code_id].n_args = n_args;
402 unique_codes[unique_code_id].u_byte.code = code;
403 unique_codes[unique_code_id].u_byte.len = len;
404
405 DEBUG_printf("assign byte code: id=%d code=%p len=%u n_args=%d\n", unique_code_id, code, len, n_args);
406}
407
408const char *py_obj_get_type_str(py_obj_t o_in) {
409 if (IS_SMALL_INT(o_in)) {
410 return "int";
411 } else {
412 py_obj_base_t *o = o_in;
413 switch (o->kind) {
414 case O_CONST:
415 if (o == py_const_none) {
416 return "NoneType";
417 } else {
418 return "bool";
419 }
420 case O_STR:
421 return "str";
422#ifdef PY_FLOAT
423 case O_FLOAT:
424 return "float";
425#endif
Damien6cdd3af2013-10-05 18:08:26 +0100426 case O_FUN_0:
427 case O_FUN_1:
428 case O_FUN_2:
429 case O_FUN_N:
430 case O_FUN_BC:
431 return "function";
Damien429d7192013-10-04 19:53:11 +0100432 case O_LIST:
433 return "list";
434 case O_SET:
435 return "set";
436 case O_MAP:
437 return "dict";
438 default:
439 assert(0);
440 return "UnknownType";
441 }
442 }
443}
444
445void py_obj_print(py_obj_t o_in) {
446 if (IS_SMALL_INT(o_in)) {
447 printf("%d", (int)FROM_SMALL_INT(o_in));
448 } else {
449 py_obj_base_t *o = o_in;
450 switch (o->kind) {
451 case O_CONST:
452 printf("%s", o->id);
453 break;
454 case O_STR:
455 // TODO need to escape chars etc
456 printf("'%s'", qstr_str(o->u_str));
457 break;
458#ifdef PY_FLOAT
459 case O_FLOAT:
460 printf("%f", o->flt);
461 break;
462#endif
463 case O_LIST:
464 printf("[");
465 for (int i = 0; i < o->u_list.len; i++) {
466 if (i > 0) {
467 printf(", ");
468 }
469 py_obj_print(o->u_list.items[i]);
470 }
471 printf("]");
472 break;
473 case O_SET:
474 {
475 bool first = true;
476 printf("{");
477 for (int i = 0; i < o->u_set.alloc; i++) {
478 if (o->u_set.table[i] != NULL) {
479 if (!first) {
480 printf(", ");
481 }
482 first = false;
483 py_obj_print(o->u_set.table[i]);
484 }
485 }
486 printf("}");
487 break;
488 }
489 case O_MAP:
490 {
491 bool first = true;
492 printf("{");
493 for (int i = 0; i < o->u_map.alloc; i++) {
494 if (o->u_map.table[i].key != NULL) {
495 if (!first) {
496 printf(", ");
497 }
498 first = false;
499 py_obj_print(o->u_map.table[i].key);
500 printf(": ");
501 py_obj_print(o->u_map.table[i].value);
502 }
503 }
504 printf("}");
505 break;
506 }
507 default:
508 assert(0);
509 }
510 }
511}
512
513int rt_is_true(py_obj_t arg) {
514 DEBUG_OP_printf("is true %p\n", arg);
515 if (IS_SMALL_INT(arg)) {
516 if (FROM_SMALL_INT(arg) == 0) {
517 return 0;
518 } else {
519 return 1;
520 }
521 } else if (arg == py_const_none) {
522 return 0;
523 } else if (arg == py_const_false) {
524 return 0;
525 } else if (arg == py_const_true) {
526 return 1;
527 } else {
528 assert(0);
529 return 0;
530 }
531}
532
533int rt_get_int(py_obj_t arg) {
534 if (IS_SMALL_INT(arg)) {
535 return FROM_SMALL_INT(arg);
536 } else {
537 assert(0);
538 return 0;
539 }
540}
541
542py_obj_t rt_load_const_str(qstr qstr) {
543 DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
544 return py_obj_new_str(qstr);
545}
546
547py_obj_t rt_load_name(qstr qstr) {
548 // logic: search locals, globals, builtins
549 DEBUG_OP_printf("load %s\n", qstr_str(qstr));
550 py_map_elem_t *elem = py_qstr_map_lookup(&map_name, qstr, false);
551 if (elem == NULL) {
552 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
553 if (elem == NULL) {
554 printf("name doesn't exist: %s\n", qstr_str(qstr));
555 assert(0);
556 }
557 }
558 return elem->value;
559}
560
561py_obj_t rt_load_global(qstr qstr) {
562 return rt_load_name(qstr); // TODO
563}
564
565py_obj_t rt_load_build_class() {
566 DEBUG_OP_printf("load_build_class\n");
567 py_map_elem_t *elem = py_qstr_map_lookup(&map_builtins, q___build_class__, false);
568 if (elem == NULL) {
569 printf("name doesn't exist: __build_class__\n");
570 assert(0);
571 }
572 return elem->value;
573}
574
575void rt_store_name(qstr qstr, py_obj_t obj) {
576 DEBUG_OP_printf("store %s <- %p\n", qstr_str(qstr), obj);
577 py_qstr_map_lookup(&map_name, qstr, true)->value = obj;
578}
579
580py_obj_t rt_unary_op(int op, py_obj_t arg) {
581 assert(0);
582 return py_const_none;
583}
584
585py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs) {
586 DEBUG_OP_printf("binary %d %p %p\n", op, lhs, rhs);
587 if (op == RT_BINARY_OP_SUBSCR) {
588 if (IS_O(lhs, O_LIST) && IS_SMALL_INT(rhs)) {
589 return ((py_obj_base_t*)lhs)->u_list.items[FROM_SMALL_INT(rhs)];
590 } else {
591 assert(0);
592 }
593 } else if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
594 py_small_int_t val;
595 switch (op) {
596 case RT_BINARY_OP_ADD:
597 case RT_BINARY_OP_INPLACE_ADD: val = FROM_SMALL_INT(lhs) + FROM_SMALL_INT(rhs); break;
598 case RT_BINARY_OP_SUBTRACT: val = FROM_SMALL_INT(lhs) - FROM_SMALL_INT(rhs); break;
599 case RT_BINARY_OP_MULTIPLY: val = FROM_SMALL_INT(lhs) * FROM_SMALL_INT(rhs); break;
600 case RT_BINARY_OP_FLOOR_DIVIDE: val = FROM_SMALL_INT(lhs) / FROM_SMALL_INT(rhs); break;
601#ifdef PY_FLOAT
602 case RT_BINARY_OP_TRUE_DIVIDE: return py_obj_new_float((float_t)FROM_SMALL_INT(lhs) / (float_t)FROM_SMALL_INT(rhs));
603#endif
604 default: printf("%d\n", op); assert(0); val = 0;
605 }
606 if (fit_small_int(val)) {
607 return TO_SMALL_INT(val);
608 }
609 } else if (IS_O(lhs, O_STR) && IS_O(rhs, O_STR)) {
610 const char *lhs_str = qstr_str(((py_obj_base_t*)lhs)->u_str);
611 const char *rhs_str = qstr_str(((py_obj_base_t*)rhs)->u_str);
612 char *val;
613 switch (op) {
614 case RT_BINARY_OP_ADD:
615 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;
616 default: printf("%d\n", op); assert(0); val = NULL;
617 }
618 return py_obj_new_str(qstr_from_str_take(val));
619 }
620 assert(0);
621 return py_const_none;
622}
623
624py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs) {
625 DEBUG_OP_printf("compare %d %p %p\n", op, lhs, rhs);
626 if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
627 int cmp;
628 switch (op) {
629 case RT_COMPARE_OP_LESS: cmp = FROM_SMALL_INT(lhs) < FROM_SMALL_INT(rhs); break;
630 case RT_COMPARE_OP_MORE: cmp = FROM_SMALL_INT(lhs) > FROM_SMALL_INT(rhs); break;
631 default: assert(0); cmp = 0;
632 }
633 if (cmp) {
634 return py_const_true;
635 } else {
636 return py_const_false;
637 }
638 }
639 assert(0);
640 return py_const_none;
641}
642
643py_obj_t rt_make_function_from_id(int unique_code_id) {
Damienb05d7072013-10-05 13:37:10 +0100644 DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id);
645 if (unique_code_id < 1 || unique_code_id >= next_unique_code_id) {
Damien429d7192013-10-04 19:53:11 +0100646 // illegal code id
647 return py_const_none;
648 }
649 py_code_t *c = &unique_codes[unique_code_id];
650 py_obj_base_t *o = m_new(py_obj_base_t, 1);
651 switch (c->kind) {
652 case PY_CODE_NATIVE:
653 switch (c->n_args) {
654 case 0: o->kind = O_FUN_0; break;
655 case 1: o->kind = O_FUN_1; break;
656 case 2: o->kind = O_FUN_2; break;
657 default: assert(0);
658 }
659 o->u_fun.fun = c->u_native.fun;
660 break;
661 case PY_CODE_BYTE:
662 o->kind = O_FUN_BC;
663 o->u_fun_bc.code = c->u_byte.code;
664 o->u_fun_bc.len = c->u_byte.len;
665 o->u_fun_bc.n_args = c->n_args;
666 break;
667 default:
668 assert(0);
669 }
670 return o;
671}
672
673py_obj_t rt_make_function_0(py_fun_0_t fun) {
674 py_obj_base_t *o = m_new(py_obj_base_t, 1);
675 o->kind = O_FUN_0;
676 o->u_fun.fun = fun;
677 return o;
678}
679
680py_obj_t rt_make_function_1(py_fun_1_t fun) {
681 py_obj_base_t *o = m_new(py_obj_base_t, 1);
682 o->kind = O_FUN_1;
683 o->u_fun.fun = fun;
684 return o;
685}
686
687py_obj_t rt_make_function_2(py_fun_2_t fun) {
688 py_obj_base_t *o = m_new(py_obj_base_t, 1);
689 o->kind = O_FUN_2;
690 o->u_fun.fun = fun;
691 return o;
692}
693
694py_obj_t rt_make_function(int n_args, py_fun_t code) {
695 // assumes code is a pointer to a py_fun_t (i think this is safe...)
696 py_obj_base_t *o = m_new(py_obj_base_t, 1);
697 o->kind = O_FUN_N;
698 o->u_fun.fun = code;
699 o->u_fun.n_args = n_args;
700 return o;
701}
702
703py_obj_t rt_call_function_0(py_obj_t fun) {
704 if (IS_O(fun, O_FUN_0)) {
705 py_obj_base_t *o = fun;
706 DEBUG_OP_printf("calling native %p...\n", o->u_fun.fun);
707 return ((py_fun_0_t)o->u_fun.fun)();
708 } else if (IS_O(fun, O_FUN_BC)) {
709 py_obj_base_t *o = fun;
710 assert(o->u_fun_bc.n_args == 0);
711 DEBUG_OP_printf("calling byte code %p...\n", o->u_fun_bc.code);
712 return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, NULL, 0);
713 } else {
714 printf("fun0:%p\n", fun);
715 assert(0);
716 return py_const_none;
717 }
718}
719
720py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) {
721 if (IS_O(fun, O_FUN_1)) {
722 py_obj_base_t *o = fun;
Damien6cdd3af2013-10-05 18:08:26 +0100723 DEBUG_OP_printf("calling native %p with 1 arg\n", o->u_fun.fun);
Damien429d7192013-10-04 19:53:11 +0100724 return ((py_fun_1_t)o->u_fun.fun)(arg);
725 } else if (IS_O(fun, O_FUN_BC)) {
726 py_obj_base_t *o = fun;
727 assert(o->u_fun_bc.n_args == 1);
Damien6cdd3af2013-10-05 18:08:26 +0100728 DEBUG_OP_printf("calling byte code %p with 1 arg\n", o->u_fun_bc.code);
Damien429d7192013-10-04 19:53:11 +0100729 return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, &arg, 1);
730 } else if (IS_O(fun, O_BOUND_METH)) {
731 py_obj_base_t *o = fun;
732 return rt_call_function_2(o->u_bound_meth.meth, o->u_bound_meth.self, arg);
733 } else {
734 printf("fun1:%p\n", fun);
735 assert(0);
736 return py_const_none;
737 }
738}
739
740py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) {
741 if (IS_O(fun, O_FUN_2)) {
742 py_obj_base_t *o = fun;
743 DEBUG_OP_printf("calling native %p...\n", o->u_fun.fun);
744 return ((py_fun_2_t)o->u_fun.fun)(arg1, arg2);
745 } else if (IS_O(fun, O_FUN_BC)) {
746 py_obj_base_t *o = fun;
747 assert(o->u_fun_bc.n_args == 2);
748 DEBUG_OP_printf("calling byte code %p...\n", o->u_fun_bc.code);
749 py_obj_t args[2];
750 args[0] = arg1;
751 args[1] = arg2;
752 return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, &args[0], 2);
753 } else {
754 assert(0);
755 return py_const_none;
756 }
757}
758
759py_obj_t rt_call_method_1(py_obj_t fun, py_obj_t self) {
760 DEBUG_OP_printf("call method %p %p\n", fun, self);
761 if (self == NULL) {
762 return rt_call_function_0(fun);
763 } else {
764 return rt_call_function_1(fun, self);
765 }
766}
767
768py_obj_t rt_call_method_2(py_obj_t fun, py_obj_t self, py_obj_t arg) {
769 DEBUG_OP_printf("call method %p %p %p\n", fun, self, arg);
770 if (self == NULL) {
771 return rt_call_function_1(fun, arg);
772 } else {
773 return rt_call_function_2(fun, self, arg);
774 }
775}
776
777// items are in reverse order
778py_obj_t rt_build_list(int n_args, py_obj_t *items) {
779 py_obj_base_t *o = m_new(py_obj_base_t, 1);
780 o->kind = O_LIST;
781 o->u_list.alloc = n_args;
782 if (o->u_list.alloc < 4) {
783 o->u_list.alloc = 4;
784 }
785 o->u_list.len = n_args;
786 o->u_list.items = m_new(py_obj_t, o->u_list.alloc);
787 for (int i = 0; i < n_args; i++) {
788 o->u_list.items[i] = items[n_args - i - 1];
789 }
790 return o;
791}
792
793py_obj_t py_set_lookup(py_obj_t o_in, py_obj_t index, bool add_if_not_found) {
794 assert(IS_O(o_in, O_SET));
795 py_obj_base_t *o = o_in;
796 int hash = py_obj_hash(index);
797 int pos = hash % o->u_set.alloc;
798 for (;;) {
799 py_obj_t elem = o->u_set.table[pos];
800 if (elem == NULL) {
801 // not in table
802 if (add_if_not_found) {
803 if (o->u_set.used + 1 >= o->u_set.alloc) {
804 // not enough room in table, rehash it
805 int old_alloc = o->u_set.alloc;
806 py_obj_t *old_table = o->u_set.table;
807 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(o->u_set.alloc + 1);
808 o->u_set.used = 0;
809 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
810 for (int i = 0; i < old_alloc; i++) {
811 if (old_table[i] != NULL) {
812 py_set_lookup(o, old_table[i], true);
813 }
814 }
815 m_free(old_table);
816 // restart the search for the new element
817 pos = hash % o->u_set.alloc;
818 } else {
819 o->u_set.used += 1;
820 o->u_set.table[pos] = index;
821 return index;
822 }
823 } else {
824 return NULL;
825 }
826 } else if (py_obj_equal(elem, index)) {
827 // found it
828 return elem;
829 } else {
830 // not yet found, keep searching in this table
831 pos = (pos + 1) % o->u_set.alloc;
832 }
833 }
834}
835
836py_obj_t rt_build_set(int n_args, py_obj_t *items) {
837 py_obj_base_t *o = m_new(py_obj_base_t, 1);
838 o->kind = O_SET;
839 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(n_args + 1);
840 o->u_set.used = 0;
841 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
842 for (int i = 0; i < o->u_set.alloc; i++) {
843 o->u_set.table[i] = NULL;
844 }
845 for (int i = 0; i < n_args; i++) {
846 py_set_lookup(o, items[i], true);
847 }
848 return o;
849}
850
851py_obj_t rt_build_map(int n_args) {
852 py_obj_base_t *o = m_new(py_obj_base_t, 1);
853 o->kind = O_MAP;
854 py_map_init(&o->u_map, MAP_PY_OBJ, n_args);
855 return o;
856}
857
858py_obj_t rt_store_map(py_obj_t map, py_obj_t key, py_obj_t value) {
859 assert(IS_O(map, O_MAP)); // should always be
860 py_map_lookup(map, key, true)->value = value;
861 return map;
862}
863
864void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t value) {
865 if (IS_O(base, O_LIST) && IS_SMALL_INT(index)) {
866 // list store
867 py_obj_base_t *o = base;
868 int idx = FROM_SMALL_INT(index);
869 if (idx < 0) {
870 idx += o->u_list.len;
871 }
872 if (0 <= idx && idx < o->u_list.len) {
873 o->u_list.items[idx] = value;
874 } else {
875 assert(0);
876 }
877 } else if (IS_O(base, O_MAP)) {
878 // map store
879 py_map_lookup(base, index, true)->value = value;
880 } else {
881 assert(0);
882 }
883}
884
885py_obj_t build_bound_method(py_obj_t self, py_obj_t meth) {
886 py_obj_base_t *o = m_new(py_obj_base_t, 1);
887 o->kind = O_BOUND_METH;
888 o->u_bound_meth.meth = meth;
889 o->u_bound_meth.self = self;
890 return o;
891}
892
893py_obj_t rt_load_attr(py_obj_t base, qstr attr) {
894 DEBUG_OP_printf("load %s\n", qstr_str(attr));
895 if (IS_O(base, O_LIST) && attr == q_append) {
896 return build_bound_method(base, fun_list_append);
897 } else if (IS_O(base, O_CLASS)) {
898 py_obj_base_t *o = base;
899 py_map_elem_t *elem = py_qstr_map_lookup(o->u_class.map, attr, false);
900 if (elem == NULL) {
901 printf("Nope! %s\n", qstr_str(attr));
902 assert(0);
903 }
904 return elem->value;
905 } else {
906 printf("AttributeError: '%s' object has no attribute '%s'\n", py_obj_get_type_str(base), qstr_str(attr));
907 assert(0);
908 return py_const_none;
909 }
910}
911
912void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest) {
913 DEBUG_OP_printf("load method %s\n", qstr_str(attr));
914 if (IS_O(base, O_LIST) && attr == q_append) {
915 dest[1] = fun_list_append;
916 dest[0] = base;
917 } else {
918 dest[1] = rt_load_attr(base, attr);
919 dest[0] = NULL;
920 }
921}
922
923void *rt_fun_table[RT_F_NUMBER_OF] = {
924 rt_load_const_str,
925 rt_load_name,
926 rt_load_global,
927 rt_load_attr,
928 rt_load_method,
929 rt_store_name,
930 rt_store_subscr,
931 rt_is_true,
932 rt_unary_op,
933 rt_build_list,
934 rt_build_map,
935 rt_store_map,
936 rt_build_set,
937 rt_make_function_from_id,
938 rt_call_function_0,
939 rt_call_function_1,
940 rt_call_function_2,
941 rt_call_method_1,
942 rt_call_method_2,
943 rt_binary_op,
944 rt_compare_op,
945};
946
947/*
948void rt_f_vector(rt_fun_kind_t fun_kind) {
949 (rt_f_table[fun_kind])();
950}
951*/