builtin.c 12.7 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 "qstr.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
// args[0] is function from class body
// args[1] is class name
// args[2:] are base objects
21
static mp_obj_t mp_builtin___build_class__(uint n_args, const mp_obj_t *args) {
Damien George's avatar
Damien George committed
22
23
    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
    // 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
    mp_obj_t meta_args[3];
49
    meta_args[0] = args[1]; // class name
Damien George's avatar
Damien George committed
50
    meta_args[1] = mp_obj_new_tuple(n_args - 2, args + 2); // tuple of bases
51
52
    meta_args[2] = class_locals; // dict of members
    mp_obj_t new_class = rt_call_function_n_kw(meta, 3, 0, meta_args);
Damien George's avatar
Damien George committed
53
54
55
56
57
58
59

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

    return new_class;
60
61
}

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

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

72
73
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin___repl_print___obj, mp_builtin___repl_print__);

74
75
76
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);
77
78
        if (val < 0) {
            val = -val;
79
        }
80
        return MP_OBJ_NEW_SMALL_INT(val);
81
#if MICROPY_ENABLE_FLOAT
82
83
    } else if (MP_OBJ_IS_TYPE(o_in, &float_type)) {
        mp_float_t value = mp_obj_float_get(o_in);
84
        // TODO check for NaN etc
85
86
        if (value < 0) {
            return mp_obj_new_float(-value);
87
        } else {
88
            return o_in;
89
        }
90
91
92
93
    } 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));
94
95
96
#endif
    } else {
        assert(0);
97
        return mp_const_none;
98
99
100
    }
}

101
102
103
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_abs_obj, mp_builtin_abs);

static mp_obj_t mp_builtin_all(mp_obj_t o_in) {
104
105
106
    mp_obj_t iterable = rt_getiter(o_in);
    mp_obj_t item;
    while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
107
        if (!rt_is_true(item)) {
108
            return mp_const_false;
109
110
        }
    }
111
    return mp_const_true;
112
113
}

114
115
116
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_all_obj, mp_builtin_all);

static mp_obj_t mp_builtin_any(mp_obj_t o_in) {
117
118
119
    mp_obj_t iterable = rt_getiter(o_in);
    mp_obj_t item;
    while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
120
        if (rt_is_true(item)) {
121
            return mp_const_true;
122
123
        }
    }
124
    return mp_const_false;
125
126
}

127
128
129
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_any_obj, mp_builtin_any);

static mp_obj_t mp_builtin_callable(mp_obj_t o_in) {
130
131
    if (mp_obj_is_callable(o_in)) {
        return mp_const_true;
132
    } else {
133
        return mp_const_false;
134
135
136
    }
}

137
138
139
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_callable_obj, mp_builtin_callable);

static mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
140
    int ord = mp_obj_get_int(o_in);
141
    if (0 <= ord && ord <= 0x10ffff) {
142
143
        byte str[1] = {ord};
        return mp_obj_new_str(str, 1, true);
144
    } else {
145
        nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "chr() arg not in range(0x110000)"));
146
    }
147
148
}

149
150
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_chr_obj, mp_builtin_chr);

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
static mp_obj_t mp_builtin_dir(uint n_args, const mp_obj_t *args) {
    // TODO make this function more general and less of a hack

    mp_map_t *map;
    if (n_args == 0) {
        // make a list of names in the local name space
        map = rt_locals_get();
    } else { // n_args == 1
        // make a list of names in the given object
        mp_obj_type_t *type = mp_obj_get_type(args[0]);
        if (type == &module_type) {
            map = mp_obj_module_get_globals(args[0]);
        } else if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &dict_type)) {
            map = mp_obj_dict_get_map(type->locals_dict);
        } else {
            return mp_obj_new_list(0, NULL);
        }
    }

    mp_obj_t dir = mp_obj_new_list(0, NULL);
    for (uint i = 0; i < map->alloc; i++) {
        if (map->table[i].key != MP_OBJ_NULL) {
            mp_obj_list_append(dir, map->table[i].key);
        }
    }
    return dir;
}

MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_dir_obj, 0, 1, mp_builtin_dir);

181
static mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
182
183
184
    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);
185
186
187
188
        mp_obj_t args[2];
        args[0] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
        args[1] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
        return rt_build_tuple(2, args);
189
    } else {
190
        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)));
191
192
193
    }
}

194
195
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_divmod_obj, mp_builtin_divmod);

196
static mp_obj_t mp_builtin_hash(mp_obj_t o_in) {
197
    // TODO hash will generally overflow small integer; can we safely truncate it?
198
    return mp_obj_new_int(mp_obj_hash(o_in));
199
200
}

201
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hash_obj, mp_builtin_hash);
202

203
204
static mp_obj_t mp_builtin_iter(mp_obj_t o_in) {
    return rt_getiter(o_in);
205
206
}

207
208
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter);

209
static mp_obj_t mp_builtin_len(mp_obj_t o_in) {
210
211
    mp_obj_t len = mp_obj_len_maybe(o_in);
    if (len == NULL) {
212
        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)));
213
214
    } else {
        return len;
215
216
217
    }
}

218
219
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_len_obj, mp_builtin_len);

220
static mp_obj_t mp_builtin_max(uint n_args, const mp_obj_t *args) {
221
222
    if (n_args == 1) {
        // given an iterable
223
224
225
226
227
        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)) {
228
229
                max_obj = item;
            }
230
        }
231
        if (max_obj == NULL) {
232
            nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "max() arg is an empty sequence"));
233
234
        }
        return max_obj;
235
    } else {
236
        // given many args
237
        mp_obj_t max_obj = args[0];
238
        for (int i = 1; i < n_args; i++) {
239
            if (mp_obj_less(max_obj, args[i])) {
240
241
242
243
                max_obj = args[i];
            }
        }
        return max_obj;
244
245
246
    }
}

247
248
MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin_max_obj, 1, mp_builtin_max);

249
static mp_obj_t mp_builtin_min(uint n_args, const mp_obj_t *args) {
250
251
    if (n_args == 1) {
        // given an iterable
252
253
254
255
256
        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)) {
257
258
259
260
                min_obj = item;
            }
        }
        if (min_obj == NULL) {
261
            nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "min() arg is an empty sequence"));
262
263
264
265
        }
        return min_obj;
    } else {
        // given many args
266
        mp_obj_t min_obj = args[0];
267
        for (int i = 1; i < n_args; i++) {
268
            if (mp_obj_less(args[i], min_obj)) {
269
270
271
272
273
274
                min_obj = args[i];
            }
        }
        return min_obj;
    }
}
275

276
277
MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin_min_obj, 1, mp_builtin_min);

278
279
280
static mp_obj_t mp_builtin_next(mp_obj_t o) {
    mp_obj_t ret = rt_iternext(o);
    if (ret == mp_const_stop_iteration) {
281
        nlr_jump(mp_obj_new_exception(MP_QSTR_StopIteration));
282
283
284
    } else {
        return ret;
    }
285
286
287
288
}

MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_next_obj, mp_builtin_next);

289
static mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
290
    uint len;
291
    const char *str = mp_obj_str_get_data(o_in, &len);
292
    if (len == 1) {
293
294
295
        // don't sign extend when converting to ord
        // TODO unicode
        return mp_obj_new_int(((const byte*)str)[0]);
296
    } else {
297
        nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "ord() expected a character, but string of length %d found", len));
298
299
    }
}
300

301
302
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_ord_obj, mp_builtin_ord);

303
static mp_obj_t mp_builtin_pow(uint n_args, const mp_obj_t *args) {
304
    assert(2 <= n_args && n_args <= 3);
305
306
    switch (n_args) {
        case 2: return rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]);
307
        default: return rt_binary_op(RT_BINARY_OP_MODULO, rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]), args[2]); // TODO optimise...
308
309
    }
}
310

311
312
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj, 2, 3, mp_builtin_pow);

313
static mp_obj_t mp_builtin_print(uint n_args, const mp_obj_t *args) {
314
315
316
317
    for (int i = 0; i < n_args; i++) {
        if (i > 0) {
            printf(" ");
        }
318
        mp_obj_print(args[i], PRINT_STR);
319
320
    }
    printf("\n");
321
    return mp_const_none;
322
323
}

324
325
MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin_print_obj, 0, mp_builtin_print);

326
static mp_obj_t mp_builtin_range(uint n_args, const mp_obj_t *args) {
327
    assert(1 <= n_args && n_args <= 3);
328
    switch (n_args) {
329
330
        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);
331
        default: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), mp_obj_get_int(args[2]));
332
333
334
    }
}

335
336
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_range_obj, 1, 3, mp_builtin_range);

Damien George's avatar
Damien George committed
337
338
static mp_obj_t mp_builtin_repr(mp_obj_t o_in) {
    vstr_t *vstr = vstr_new();
339
    mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))vstr_printf, vstr, o_in, PRINT_REPR);
340
341
342
    mp_obj_t s = mp_obj_new_str((byte*)vstr->buf, vstr->len, false);
    vstr_free(vstr);
    return s;
Damien George's avatar
Damien George committed
343
344
345
346
}

MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr);

347
static mp_obj_t mp_builtin_sum(uint n_args, const mp_obj_t *args) {
348
    assert(1 <= n_args && n_args <= 2);
349
    mp_obj_t value;
350
    switch (n_args) {
351
        case 1: value = mp_obj_new_int(0); break;
352
        default: value = args[1]; break;
353
    }
354
355
356
    mp_obj_t iterable = rt_getiter(args[0]);
    mp_obj_t item;
    while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
357
358
359
360
        value = rt_binary_op(RT_BINARY_OP_ADD, value, item);
    }
    return value;
}
Damien George's avatar
Damien George committed
361

362
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum);
John R. Lenton's avatar
sorted    
John R. Lenton committed
363

364
365
366
static mp_obj_t mp_builtin_sorted(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) {
    assert(n_args >= 1);
    if (n_args > 1) {
John R. Lenton's avatar
sorted    
John R. Lenton committed
367
368
369
        nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError,
                                          "must use keyword argument for key function"));
    }
370
371
    mp_obj_t self = list_type.make_new((mp_obj_t)&list_type, 1, 0, args);
    mp_obj_list_sort(1, &self, kwargs);
John R. Lenton's avatar
sorted    
John R. Lenton committed
372
373
374

    return self;
}
Damien George's avatar
Damien George committed
375

376
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, 1, mp_builtin_sorted);
377

378
static mp_obj_t mp_builtin_str(mp_obj_t o_in) {
379
    vstr_t *vstr = vstr_new();
380
    mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, o_in, PRINT_STR);
381
382
383
    mp_obj_t s = mp_obj_new_str((byte*)vstr->buf, vstr->len, false);
    vstr_free(vstr);
    return s;
384
385
386
}

MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_str_obj, mp_builtin_str);
387
388
389
390
391
392
393
394
395
396
397
398

// TODO: This should be type, this is just quick CPython compat hack
static mp_obj_t mp_builtin_bytes(uint n_args, const mp_obj_t *args) {
    if (!MP_OBJ_IS_QSTR(args[0]) && !MP_OBJ_IS_TYPE(args[0], &str_type)) {
        assert(0);
    }
    // Currently, MicroPython strings are mix between CPython byte and unicode
    // strings. So, conversion is null so far.
    return args[0];
}

MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_bytes_obj, 1, 3, mp_builtin_bytes);
399
400

static mp_obj_t mp_builtin_id(mp_obj_t o_in) {
401
    return mp_obj_new_int((machine_int_t)o_in);
402
403
404
}

MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_id_obj, mp_builtin_id);