summaryrefslogtreecommitdiffstatshomepage
path: root/py/builtin.c
blob: 8b380b231086561c6672347fbc4f533fca11fb92 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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));
    }
}