blob: 21f3c8c50adc8261035bb7fbed16763d1661d03f [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
12#define DEBUG_printf(args...) (void)0
13//#define DEBUG_printf(args...) printf(args)
14
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
426 case O_LIST:
427 return "list";
428 case O_SET:
429 return "set";
430 case O_MAP:
431 return "dict";
432 default:
433 assert(0);
434 return "UnknownType";
435 }
436 }
437}
438
439void py_obj_print(py_obj_t o_in) {
440 if (IS_SMALL_INT(o_in)) {
441 printf("%d", (int)FROM_SMALL_INT(o_in));
442 } else {
443 py_obj_base_t *o = o_in;
444 switch (o->kind) {
445 case O_CONST:
446 printf("%s", o->id);
447 break;
448 case O_STR:
449 // TODO need to escape chars etc
450 printf("'%s'", qstr_str(o->u_str));
451 break;
452#ifdef PY_FLOAT
453 case O_FLOAT:
454 printf("%f", o->flt);
455 break;
456#endif
457 case O_LIST:
458 printf("[");
459 for (int i = 0; i < o->u_list.len; i++) {
460 if (i > 0) {
461 printf(", ");
462 }
463 py_obj_print(o->u_list.items[i]);
464 }
465 printf("]");
466 break;
467 case O_SET:
468 {
469 bool first = true;
470 printf("{");
471 for (int i = 0; i < o->u_set.alloc; i++) {
472 if (o->u_set.table[i] != NULL) {
473 if (!first) {
474 printf(", ");
475 }
476 first = false;
477 py_obj_print(o->u_set.table[i]);
478 }
479 }
480 printf("}");
481 break;
482 }
483 case O_MAP:
484 {
485 bool first = true;
486 printf("{");
487 for (int i = 0; i < o->u_map.alloc; i++) {
488 if (o->u_map.table[i].key != NULL) {
489 if (!first) {
490 printf(", ");
491 }
492 first = false;
493 py_obj_print(o->u_map.table[i].key);
494 printf(": ");
495 py_obj_print(o->u_map.table[i].value);
496 }
497 }
498 printf("}");
499 break;
500 }
501 default:
502 assert(0);
503 }
504 }
505}
506
507int rt_is_true(py_obj_t arg) {
508 DEBUG_OP_printf("is true %p\n", arg);
509 if (IS_SMALL_INT(arg)) {
510 if (FROM_SMALL_INT(arg) == 0) {
511 return 0;
512 } else {
513 return 1;
514 }
515 } else if (arg == py_const_none) {
516 return 0;
517 } else if (arg == py_const_false) {
518 return 0;
519 } else if (arg == py_const_true) {
520 return 1;
521 } else {
522 assert(0);
523 return 0;
524 }
525}
526
527int rt_get_int(py_obj_t arg) {
528 if (IS_SMALL_INT(arg)) {
529 return FROM_SMALL_INT(arg);
530 } else {
531 assert(0);
532 return 0;
533 }
534}
535
536py_obj_t rt_load_const_str(qstr qstr) {
537 DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
538 return py_obj_new_str(qstr);
539}
540
541py_obj_t rt_load_name(qstr qstr) {
542 // logic: search locals, globals, builtins
543 DEBUG_OP_printf("load %s\n", qstr_str(qstr));
544 py_map_elem_t *elem = py_qstr_map_lookup(&map_name, qstr, false);
545 if (elem == NULL) {
546 elem = py_qstr_map_lookup(&map_builtins, qstr, false);
547 if (elem == NULL) {
548 printf("name doesn't exist: %s\n", qstr_str(qstr));
549 assert(0);
550 }
551 }
552 return elem->value;
553}
554
555py_obj_t rt_load_global(qstr qstr) {
556 return rt_load_name(qstr); // TODO
557}
558
559py_obj_t rt_load_build_class() {
560 DEBUG_OP_printf("load_build_class\n");
561 py_map_elem_t *elem = py_qstr_map_lookup(&map_builtins, q___build_class__, false);
562 if (elem == NULL) {
563 printf("name doesn't exist: __build_class__\n");
564 assert(0);
565 }
566 return elem->value;
567}
568
569void rt_store_name(qstr qstr, py_obj_t obj) {
570 DEBUG_OP_printf("store %s <- %p\n", qstr_str(qstr), obj);
571 py_qstr_map_lookup(&map_name, qstr, true)->value = obj;
572}
573
574py_obj_t rt_unary_op(int op, py_obj_t arg) {
575 assert(0);
576 return py_const_none;
577}
578
579py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs) {
580 DEBUG_OP_printf("binary %d %p %p\n", op, lhs, rhs);
581 if (op == RT_BINARY_OP_SUBSCR) {
582 if (IS_O(lhs, O_LIST) && IS_SMALL_INT(rhs)) {
583 return ((py_obj_base_t*)lhs)->u_list.items[FROM_SMALL_INT(rhs)];
584 } else {
585 assert(0);
586 }
587 } else if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
588 py_small_int_t val;
589 switch (op) {
590 case RT_BINARY_OP_ADD:
591 case RT_BINARY_OP_INPLACE_ADD: val = FROM_SMALL_INT(lhs) + FROM_SMALL_INT(rhs); break;
592 case RT_BINARY_OP_SUBTRACT: val = FROM_SMALL_INT(lhs) - FROM_SMALL_INT(rhs); break;
593 case RT_BINARY_OP_MULTIPLY: val = FROM_SMALL_INT(lhs) * FROM_SMALL_INT(rhs); break;
594 case RT_BINARY_OP_FLOOR_DIVIDE: val = FROM_SMALL_INT(lhs) / FROM_SMALL_INT(rhs); break;
595#ifdef PY_FLOAT
596 case RT_BINARY_OP_TRUE_DIVIDE: return py_obj_new_float((float_t)FROM_SMALL_INT(lhs) / (float_t)FROM_SMALL_INT(rhs));
597#endif
598 default: printf("%d\n", op); assert(0); val = 0;
599 }
600 if (fit_small_int(val)) {
601 return TO_SMALL_INT(val);
602 }
603 } else if (IS_O(lhs, O_STR) && IS_O(rhs, O_STR)) {
604 const char *lhs_str = qstr_str(((py_obj_base_t*)lhs)->u_str);
605 const char *rhs_str = qstr_str(((py_obj_base_t*)rhs)->u_str);
606 char *val;
607 switch (op) {
608 case RT_BINARY_OP_ADD:
609 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;
610 default: printf("%d\n", op); assert(0); val = NULL;
611 }
612 return py_obj_new_str(qstr_from_str_take(val));
613 }
614 assert(0);
615 return py_const_none;
616}
617
618py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs) {
619 DEBUG_OP_printf("compare %d %p %p\n", op, lhs, rhs);
620 if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) {
621 int cmp;
622 switch (op) {
623 case RT_COMPARE_OP_LESS: cmp = FROM_SMALL_INT(lhs) < FROM_SMALL_INT(rhs); break;
624 case RT_COMPARE_OP_MORE: cmp = FROM_SMALL_INT(lhs) > FROM_SMALL_INT(rhs); break;
625 default: assert(0); cmp = 0;
626 }
627 if (cmp) {
628 return py_const_true;
629 } else {
630 return py_const_false;
631 }
632 }
633 assert(0);
634 return py_const_none;
635}
636
637py_obj_t rt_make_function_from_id(int unique_code_id) {
Damienb05d7072013-10-05 13:37:10 +0100638 DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id);
639 if (unique_code_id < 1 || unique_code_id >= next_unique_code_id) {
Damien429d7192013-10-04 19:53:11 +0100640 // illegal code id
641 return py_const_none;
642 }
643 py_code_t *c = &unique_codes[unique_code_id];
644 py_obj_base_t *o = m_new(py_obj_base_t, 1);
645 switch (c->kind) {
646 case PY_CODE_NATIVE:
647 switch (c->n_args) {
648 case 0: o->kind = O_FUN_0; break;
649 case 1: o->kind = O_FUN_1; break;
650 case 2: o->kind = O_FUN_2; break;
651 default: assert(0);
652 }
653 o->u_fun.fun = c->u_native.fun;
654 break;
655 case PY_CODE_BYTE:
656 o->kind = O_FUN_BC;
657 o->u_fun_bc.code = c->u_byte.code;
658 o->u_fun_bc.len = c->u_byte.len;
659 o->u_fun_bc.n_args = c->n_args;
660 break;
661 default:
662 assert(0);
663 }
664 return o;
665}
666
667py_obj_t rt_make_function_0(py_fun_0_t fun) {
668 py_obj_base_t *o = m_new(py_obj_base_t, 1);
669 o->kind = O_FUN_0;
670 o->u_fun.fun = fun;
671 return o;
672}
673
674py_obj_t rt_make_function_1(py_fun_1_t fun) {
675 py_obj_base_t *o = m_new(py_obj_base_t, 1);
676 o->kind = O_FUN_1;
677 o->u_fun.fun = fun;
678 return o;
679}
680
681py_obj_t rt_make_function_2(py_fun_2_t fun) {
682 py_obj_base_t *o = m_new(py_obj_base_t, 1);
683 o->kind = O_FUN_2;
684 o->u_fun.fun = fun;
685 return o;
686}
687
688py_obj_t rt_make_function(int n_args, py_fun_t code) {
689 // assumes code is a pointer to a py_fun_t (i think this is safe...)
690 py_obj_base_t *o = m_new(py_obj_base_t, 1);
691 o->kind = O_FUN_N;
692 o->u_fun.fun = code;
693 o->u_fun.n_args = n_args;
694 return o;
695}
696
697py_obj_t rt_call_function_0(py_obj_t fun) {
698 if (IS_O(fun, O_FUN_0)) {
699 py_obj_base_t *o = fun;
700 DEBUG_OP_printf("calling native %p...\n", o->u_fun.fun);
701 return ((py_fun_0_t)o->u_fun.fun)();
702 } else if (IS_O(fun, O_FUN_BC)) {
703 py_obj_base_t *o = fun;
704 assert(o->u_fun_bc.n_args == 0);
705 DEBUG_OP_printf("calling byte code %p...\n", o->u_fun_bc.code);
706 return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, NULL, 0);
707 } else {
708 printf("fun0:%p\n", fun);
709 assert(0);
710 return py_const_none;
711 }
712}
713
714py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) {
715 if (IS_O(fun, O_FUN_1)) {
716 py_obj_base_t *o = fun;
717 DEBUG_OP_printf("calling native %p...\n", o->u_fun.fun);
718 return ((py_fun_1_t)o->u_fun.fun)(arg);
719 } else if (IS_O(fun, O_FUN_BC)) {
720 py_obj_base_t *o = fun;
721 assert(o->u_fun_bc.n_args == 1);
722 DEBUG_OP_printf("calling byte code %p...\n", o->u_fun_bc.code);
723 return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, &arg, 1);
724 } else if (IS_O(fun, O_BOUND_METH)) {
725 py_obj_base_t *o = fun;
726 return rt_call_function_2(o->u_bound_meth.meth, o->u_bound_meth.self, arg);
727 } else {
728 printf("fun1:%p\n", fun);
729 assert(0);
730 return py_const_none;
731 }
732}
733
734py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) {
735 if (IS_O(fun, O_FUN_2)) {
736 py_obj_base_t *o = fun;
737 DEBUG_OP_printf("calling native %p...\n", o->u_fun.fun);
738 return ((py_fun_2_t)o->u_fun.fun)(arg1, arg2);
739 } else if (IS_O(fun, O_FUN_BC)) {
740 py_obj_base_t *o = fun;
741 assert(o->u_fun_bc.n_args == 2);
742 DEBUG_OP_printf("calling byte code %p...\n", o->u_fun_bc.code);
743 py_obj_t args[2];
744 args[0] = arg1;
745 args[1] = arg2;
746 return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, &args[0], 2);
747 } else {
748 assert(0);
749 return py_const_none;
750 }
751}
752
753py_obj_t rt_call_method_1(py_obj_t fun, py_obj_t self) {
754 DEBUG_OP_printf("call method %p %p\n", fun, self);
755 if (self == NULL) {
756 return rt_call_function_0(fun);
757 } else {
758 return rt_call_function_1(fun, self);
759 }
760}
761
762py_obj_t rt_call_method_2(py_obj_t fun, py_obj_t self, py_obj_t arg) {
763 DEBUG_OP_printf("call method %p %p %p\n", fun, self, arg);
764 if (self == NULL) {
765 return rt_call_function_1(fun, arg);
766 } else {
767 return rt_call_function_2(fun, self, arg);
768 }
769}
770
771// items are in reverse order
772py_obj_t rt_build_list(int n_args, py_obj_t *items) {
773 py_obj_base_t *o = m_new(py_obj_base_t, 1);
774 o->kind = O_LIST;
775 o->u_list.alloc = n_args;
776 if (o->u_list.alloc < 4) {
777 o->u_list.alloc = 4;
778 }
779 o->u_list.len = n_args;
780 o->u_list.items = m_new(py_obj_t, o->u_list.alloc);
781 for (int i = 0; i < n_args; i++) {
782 o->u_list.items[i] = items[n_args - i - 1];
783 }
784 return o;
785}
786
787py_obj_t py_set_lookup(py_obj_t o_in, py_obj_t index, bool add_if_not_found) {
788 assert(IS_O(o_in, O_SET));
789 py_obj_base_t *o = o_in;
790 int hash = py_obj_hash(index);
791 int pos = hash % o->u_set.alloc;
792 for (;;) {
793 py_obj_t elem = o->u_set.table[pos];
794 if (elem == NULL) {
795 // not in table
796 if (add_if_not_found) {
797 if (o->u_set.used + 1 >= o->u_set.alloc) {
798 // not enough room in table, rehash it
799 int old_alloc = o->u_set.alloc;
800 py_obj_t *old_table = o->u_set.table;
801 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(o->u_set.alloc + 1);
802 o->u_set.used = 0;
803 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
804 for (int i = 0; i < old_alloc; i++) {
805 if (old_table[i] != NULL) {
806 py_set_lookup(o, old_table[i], true);
807 }
808 }
809 m_free(old_table);
810 // restart the search for the new element
811 pos = hash % o->u_set.alloc;
812 } else {
813 o->u_set.used += 1;
814 o->u_set.table[pos] = index;
815 return index;
816 }
817 } else {
818 return NULL;
819 }
820 } else if (py_obj_equal(elem, index)) {
821 // found it
822 return elem;
823 } else {
824 // not yet found, keep searching in this table
825 pos = (pos + 1) % o->u_set.alloc;
826 }
827 }
828}
829
830py_obj_t rt_build_set(int n_args, py_obj_t *items) {
831 py_obj_base_t *o = m_new(py_obj_base_t, 1);
832 o->kind = O_SET;
833 o->u_set.alloc = get_doubling_prime_greater_or_equal_to(n_args + 1);
834 o->u_set.used = 0;
835 o->u_set.table = m_new(py_obj_t, o->u_set.alloc);
836 for (int i = 0; i < o->u_set.alloc; i++) {
837 o->u_set.table[i] = NULL;
838 }
839 for (int i = 0; i < n_args; i++) {
840 py_set_lookup(o, items[i], true);
841 }
842 return o;
843}
844
845py_obj_t rt_build_map(int n_args) {
846 py_obj_base_t *o = m_new(py_obj_base_t, 1);
847 o->kind = O_MAP;
848 py_map_init(&o->u_map, MAP_PY_OBJ, n_args);
849 return o;
850}
851
852py_obj_t rt_store_map(py_obj_t map, py_obj_t key, py_obj_t value) {
853 assert(IS_O(map, O_MAP)); // should always be
854 py_map_lookup(map, key, true)->value = value;
855 return map;
856}
857
858void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t value) {
859 if (IS_O(base, O_LIST) && IS_SMALL_INT(index)) {
860 // list store
861 py_obj_base_t *o = base;
862 int idx = FROM_SMALL_INT(index);
863 if (idx < 0) {
864 idx += o->u_list.len;
865 }
866 if (0 <= idx && idx < o->u_list.len) {
867 o->u_list.items[idx] = value;
868 } else {
869 assert(0);
870 }
871 } else if (IS_O(base, O_MAP)) {
872 // map store
873 py_map_lookup(base, index, true)->value = value;
874 } else {
875 assert(0);
876 }
877}
878
879py_obj_t build_bound_method(py_obj_t self, py_obj_t meth) {
880 py_obj_base_t *o = m_new(py_obj_base_t, 1);
881 o->kind = O_BOUND_METH;
882 o->u_bound_meth.meth = meth;
883 o->u_bound_meth.self = self;
884 return o;
885}
886
887py_obj_t rt_load_attr(py_obj_t base, qstr attr) {
888 DEBUG_OP_printf("load %s\n", qstr_str(attr));
889 if (IS_O(base, O_LIST) && attr == q_append) {
890 return build_bound_method(base, fun_list_append);
891 } else if (IS_O(base, O_CLASS)) {
892 py_obj_base_t *o = base;
893 py_map_elem_t *elem = py_qstr_map_lookup(o->u_class.map, attr, false);
894 if (elem == NULL) {
895 printf("Nope! %s\n", qstr_str(attr));
896 assert(0);
897 }
898 return elem->value;
899 } else {
900 printf("AttributeError: '%s' object has no attribute '%s'\n", py_obj_get_type_str(base), qstr_str(attr));
901 assert(0);
902 return py_const_none;
903 }
904}
905
906void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest) {
907 DEBUG_OP_printf("load method %s\n", qstr_str(attr));
908 if (IS_O(base, O_LIST) && attr == q_append) {
909 dest[1] = fun_list_append;
910 dest[0] = base;
911 } else {
912 dest[1] = rt_load_attr(base, attr);
913 dest[0] = NULL;
914 }
915}
916
917void *rt_fun_table[RT_F_NUMBER_OF] = {
918 rt_load_const_str,
919 rt_load_name,
920 rt_load_global,
921 rt_load_attr,
922 rt_load_method,
923 rt_store_name,
924 rt_store_subscr,
925 rt_is_true,
926 rt_unary_op,
927 rt_build_list,
928 rt_build_map,
929 rt_store_map,
930 rt_build_set,
931 rt_make_function_from_id,
932 rt_call_function_0,
933 rt_call_function_1,
934 rt_call_function_2,
935 rt_call_method_1,
936 rt_call_method_2,
937 rt_binary_op,
938 rt_compare_op,
939};
940
941/*
942void rt_f_vector(rt_fun_kind_t fun_kind) {
943 (rt_f_table[fun_kind])();
944}
945*/