builtin.c 10.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>

#include "nlr.h"
#include "misc.h"
10
#include "mpconfig.h"
11
#include "mpqstr.h"
12
13
#include "obj.h"
#include "runtime0.h"
14
15
16
17
#include "runtime.h"
#include "map.h"
#include "builtin.h"

Damien George's avatar
Damien George committed
18
19
20
21
22
23
// args[0] is function from class body
// args[1] is class name
// args[2:] are base objects
mp_obj_t mp_builtin___build_class__(int n_args, const mp_obj_t *args) {
    assert(2 <= n_args);

24
    // we differ from CPython: we set the new __locals__ object here
25
    mp_map_t *old_locals = rt_locals_get();
26
27
    mp_obj_t class_locals = mp_obj_new_dict(0);
    rt_locals_set(mp_obj_dict_get_map(class_locals));
28
29

    // call the class code
Damien George's avatar
Damien George committed
30
    mp_obj_t cell = rt_call_function_1(args[0], (mp_obj_t)0xdeadbeef);
31
32

    // restore old __locals__ object
33
    rt_locals_set(old_locals);
34

Damien George's avatar
Damien George committed
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    // get the class type (meta object) from the base objects
    mp_obj_t meta;
    if (n_args == 2) {
        // no explicit bases, so use 'type'
        meta = (mp_obj_t)&mp_const_type;
    } else {
        // use type of first base object
        meta = mp_obj_get_type(args[2]);
    }

    // TODO do proper metaclass resolution for multiple base objects

    // create the new class using a call to the meta object
    // (arguments must be backwards in the array)
    mp_obj_t meta_args[3];
    meta_args[2] = args[1]; // class name
    meta_args[1] = mp_obj_new_tuple(n_args - 2, args + 2); // tuple of bases
52
    meta_args[0] = class_locals; // dict of members
Damien George's avatar
Damien George committed
53
54
55
56
57
58
59
60
    mp_obj_t new_class = rt_call_function_n(meta, 3, meta_args);

    // store into cell if neede
    if (cell != mp_const_none) {
        mp_obj_cell_set(cell, new_class);
    }

    return new_class;
61
62
}

Damien George's avatar
Damien George committed
63
64
MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj, 2, mp_builtin___build_class__);

65
66
67
mp_obj_t mp_builtin___repl_print__(mp_obj_t o) {
    if (o != mp_const_none) {
        mp_obj_print(o);
68
69
        printf("\n");
    }
70
    return mp_const_none;
71
72
}

73
74
75
mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
    if (MP_OBJ_IS_SMALL_INT(o_in)) {
        mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(o_in);
76
77
        if (val < 0) {
            val = -val;
78
        }
79
        return MP_OBJ_NEW_SMALL_INT(val);
80
#if MICROPY_ENABLE_FLOAT
81
82
    } else if (MP_OBJ_IS_TYPE(o_in, &float_type)) {
        mp_float_t value = mp_obj_float_get(o_in);
83
        // TODO check for NaN etc
84
85
        if (value < 0) {
            return mp_obj_new_float(-value);
86
        } else {
87
            return o_in;
88
        }
89
90
91
92
    } else if (MP_OBJ_IS_TYPE(o_in, &complex_type)) {
        mp_float_t real, imag;
        mp_obj_complex_get(o_in, &real, &imag);
        return mp_obj_new_float(machine_sqrt(real*real + imag*imag));
93
94
95
#endif
    } else {
        assert(0);
96
        return mp_const_none;
97
98
99
    }
}

100
101
102
103
mp_obj_t mp_builtin_all(mp_obj_t o_in) {
    mp_obj_t iterable = rt_getiter(o_in);
    mp_obj_t item;
    while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
104
        if (!rt_is_true(item)) {
105
            return mp_const_false;
106
107
        }
    }
108
    return mp_const_true;
109
110
}

111
112
113
114
mp_obj_t mp_builtin_any(mp_obj_t o_in) {
    mp_obj_t iterable = rt_getiter(o_in);
    mp_obj_t item;
    while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
115
        if (rt_is_true(item)) {
116
            return mp_const_true;
117
118
        }
    }
119
    return mp_const_false;
120
121
}

122
123
124
mp_obj_t mp_builtin_callable(mp_obj_t o_in) {
    if (mp_obj_is_callable(o_in)) {
        return mp_const_true;
125
    } else {
126
        return mp_const_false;
127
128
129
    }
}

130
131
mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
    int ord = mp_obj_get_int(o_in);
132
133
134
135
    if (0 <= ord && ord <= 0x10ffff) {
        char *str = m_new(char, 2);
        str[0] = ord;
        str[1] = '\0';
136
        return mp_obj_new_str(qstr_from_str_take(str, 2));
137
    } else {
138
        nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "chr() arg not in range(0x110000)"));
139
    }
140
141
}

142
143
144
145
146
147
148
mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
    if (MP_OBJ_IS_SMALL_INT(o1_in) && MP_OBJ_IS_SMALL_INT(o2_in)) {
        mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in);
        mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in);
        mp_obj_t revs_args[2];
        revs_args[1] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
        revs_args[0] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
149
150
        return rt_build_tuple(2, revs_args);
    } else {
151
        nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in)));
152
153
154
    }
}

155
static mp_obj_t mp_builtin_hash(mp_obj_t o_in) {
156
    // TODO hash will generally overflow small integer; can we safely truncate it?
157
    return mp_obj_new_int(mp_obj_hash(o_in));
158
159
}

160
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hash_obj, mp_builtin_hash);
161

162
163
static mp_obj_t mp_builtin_iter(mp_obj_t o_in) {
    return rt_getiter(o_in);
164
165
}

166
167
168
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter);

mp_obj_t mp_builtin_len(mp_obj_t o_in) {
169
170
    mp_obj_t len = mp_obj_len_maybe(o_in);
    if (len == NULL) {
171
        nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in)));
172
173
    } else {
        return len;
174
175
176
    }
}

177
mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args) {
178
179
    if (n_args == 1) {
        // given an iterable
180
181
182
183
184
        mp_obj_t iterable = rt_getiter(args[0]);
        mp_obj_t max_obj = NULL;
        mp_obj_t item;
        while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
            if (max_obj == NULL || mp_obj_less(max_obj, item)) {
185
186
                max_obj = item;
            }
187
        }
188
        if (max_obj == NULL) {
189
            nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "max() arg is an empty sequence"));
190
191
        }
        return max_obj;
192
    } else {
193
        // given many args
194
        mp_obj_t max_obj = args[0];
195
        for (int i = 1; i < n_args; i++) {
196
            if (mp_obj_less(max_obj, args[i])) {
197
198
199
200
                max_obj = args[i];
            }
        }
        return max_obj;
201
202
203
    }
}

204
mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args) {
205
206
    if (n_args == 1) {
        // given an iterable
207
208
209
210
211
        mp_obj_t iterable = rt_getiter(args[0]);
        mp_obj_t min_obj = NULL;
        mp_obj_t item;
        while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
            if (min_obj == NULL || mp_obj_less(item, min_obj)) {
212
213
214
215
                min_obj = item;
            }
        }
        if (min_obj == NULL) {
216
            nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "min() arg is an empty sequence"));
217
218
219
220
        }
        return min_obj;
    } else {
        // given many args
221
        mp_obj_t min_obj = args[0];
222
        for (int i = 1; i < n_args; i++) {
223
            if (mp_obj_less(args[i], min_obj)) {
224
225
226
227
228
229
                min_obj = args[i];
            }
        }
        return min_obj;
    }
}
230

231
232
233
static mp_obj_t mp_builtin_next(mp_obj_t o) {
    mp_obj_t ret = rt_iternext(o);
    if (ret == mp_const_stop_iteration) {
234
        nlr_jump(mp_obj_new_exception(MP_QSTR_StopIteration));
235
236
237
    } else {
        return ret;
    }
238
239
240
241
242
243
}

MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_next_obj, mp_builtin_next);

mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
    const char *str = qstr_str(mp_obj_get_qstr(o_in));
244
    if (strlen(str) == 1) {
245
        return mp_obj_new_int(str[0]);
246
    } else {
247
        nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "ord() expected a character, but string of length %d found", strlen(str)));
248
249
    }
}
250

251
mp_obj_t mp_builtin_pow(int n_args, const mp_obj_t *args) {
252
253
254
    switch (n_args) {
        case 2: return rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]);
        case 3: return rt_binary_op(RT_BINARY_OP_MODULO, rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]), args[2]); // TODO optimise...
255
        default: nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "pow expected at most 3 arguments, got %d", n_args));
256
257
    }
}
258

259
mp_obj_t mp_builtin_print(int n_args, const mp_obj_t *args) {
260
261
262
263
    for (int i = 0; i < n_args; i++) {
        if (i > 0) {
            printf(" ");
        }
264
        if (MP_OBJ_IS_TYPE(args[i], &str_type)) {
265
            // special case, print string raw
266
            printf("%s", qstr_str(mp_obj_str_get(args[i])));
267
268
        } else {
            // print the object Python style
269
            mp_obj_print(args[i]);
270
271
272
        }
    }
    printf("\n");
273
    return mp_const_none;
274
275
}

276
mp_obj_t mp_builtin_range(int n_args, const mp_obj_t *args) {
277
    switch (n_args) {
278
279
280
        case 1: return mp_obj_new_range(0, mp_obj_get_int(args[0]), 1);
        case 2: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), 1);
        case 3: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), mp_obj_get_int(args[2]));
281
        default: nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "range expected at most 3 arguments, got %d", n_args));
282
283
284
285
286
    }
}

mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) {
    mp_obj_t value;
287
    switch (n_args) {
288
        case 1: value = mp_obj_new_int(0); break;
289
        case 2: value = args[1]; break;
290
        default: nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "sum expected at most 2 arguments, got %d", n_args));
291
    }
292
293
294
    mp_obj_t iterable = rt_getiter(args[0]);
    mp_obj_t item;
    while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
295
296
297
298
        value = rt_binary_op(RT_BINARY_OP_ADD, value, item);
    }
    return value;
}
John R. Lenton's avatar
sorted    
John R. Lenton committed
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324

extern mp_obj_t list_sort(mp_obj_t args, mp_map_t *kwargs);
static mp_obj_t mp_builtin_sorted(mp_obj_t args, mp_map_t *kwargs) {
    mp_obj_t *args_items = NULL;
    uint args_len = 0;

    assert(MP_OBJ_IS_TYPE(args, &tuple_type));
    mp_obj_tuple_get(args, &args_len, &args_items);
    assert(args_len >= 1);
    if (args_len > 1) {
        nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError,
                                          "must use keyword argument for key function"));
    }
    mp_obj_t iterable = rt_getiter(args_items[0]);
    mp_obj_t self = rt_build_list(0, NULL);
    mp_obj_t item;
    while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
        rt_list_append(self, item);
    }

    mp_obj_t new_args = rt_build_tuple(1, &self);
    list_sort(new_args, kwargs);

    return self;
}
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, mp_builtin_sorted);