py: split runtime into map, obj, builtin.
diff --git a/py/builtin.c b/py/builtin.c
new file mode 100644
index 0000000..8b380b2
--- /dev/null
+++ b/py/builtin.c
@@ -0,0 +1,113 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+
+#include "nlr.h"
+#include "misc.h"
+#include "mpyconfig.h"
+#include "runtime.h"
+#include "bc.h"
+
+#include "map.h"
+#include "obj.h"
+#include "objprivate.h"
+#include "builtin.h"
+
+py_obj_t py_builtin___repl_print__(py_obj_t o) {
+ if (o != py_const_none) {
+ py_obj_print(o);
+ printf("\n");
+ }
+ return py_const_none;
+}
+
+py_obj_t py_builtin_print(int n_args, const py_obj_t* args) {
+ for (int i = 0; i < n_args; i++) {
+ if (i > 0) {
+ printf(" ");
+ }
+ if (IS_O(args[i], O_STR)) {
+ // special case, print string raw
+ printf("%s", qstr_str(((py_obj_base_t*)args[i])->u_str));
+ } else {
+ // print the object Python style
+ py_obj_print(args[i]);
+ }
+ }
+ printf("\n");
+ return py_const_none;
+}
+
+py_obj_t py_builtin_len(py_obj_t o_in) {
+ py_small_int_t len = 0;
+ if (IS_O(o_in, O_STR)) {
+ py_obj_base_t *o = o_in;
+ len = strlen(qstr_str(o->u_str));
+ } else if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) {
+ py_obj_base_t *o = o_in;
+ len = o->u_tuple_list.len;
+ } else if (IS_O(o_in, O_MAP)) {
+ py_obj_base_t *o = o_in;
+ len = o->u_map.used;
+ } else {
+ assert(0);
+ }
+ return TO_SMALL_INT(len);
+}
+
+py_obj_t py_builtin_abs(py_obj_t o_in) {
+ if (IS_SMALL_INT(o_in)) {
+ py_small_int_t val = FROM_SMALL_INT(o_in);
+ if (val < 0) {
+ val = -val;
+ }
+ return TO_SMALL_INT(val);
+#if MICROPY_ENABLE_FLOAT
+ } else if (IS_O(o_in, O_FLOAT)) {
+ py_obj_base_t *o = o_in;
+ // TODO check for NaN etc
+ if (o->u_float < 0) {
+ return py_obj_new_float(-o->u_float);
+ } else {
+ return o_in;
+ }
+ } else if (IS_O(o_in, O_COMPLEX)) {
+ py_obj_base_t *o = o_in;
+ return py_obj_new_float(machine_sqrt(o->u_complex.real*o->u_complex.real + o->u_complex.imag*o->u_complex.imag));
+#endif
+ } else {
+ assert(0);
+ return py_const_none;
+ }
+}
+
+py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name) {
+ // we differ from CPython: we set the new __locals__ object here
+ py_map_t *old_locals = rt_get_map_locals();
+ py_map_t *class_locals = py_map_new(MAP_QSTR, 0);
+ rt_set_map_locals(class_locals);
+
+ // call the class code
+ rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef);
+
+ // restore old __locals__ object
+ rt_set_map_locals(old_locals);
+
+ // create and return the new class
+ py_obj_base_t *o = m_new(py_obj_base_t, 1);
+ o->kind = O_CLASS;
+ o->u_class.locals = class_locals;
+ return o;
+}
+
+py_obj_t py_builtin_range(int n_args, const py_obj_t* args) {
+ switch (n_args) {
+ case 1: return py_obj_new_range(0, py_obj_get_int(args[0]), 1);
+ case 2: return py_obj_new_range(py_obj_get_int(args[0]), py_obj_get_int(args[1]), 1);
+ case 3: return py_obj_new_range(py_obj_get_int(args[0]), py_obj_get_int(args[1]), py_obj_get_int(args[2]));
+ default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "range expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args, NULL));
+ }
+}