modbuiltins.c 27.9 KB
Newer Older
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
/*
 * This file is part of the Micro Python project, http://micropython.org/
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2013, 2014 Damien P. George
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

27
28
29
#include <stdio.h>
#include <assert.h>

30
31
#include "py/nlr.h"
#include "py/smallint.h"
32
#include "py/objint.h"
33
34
35
36
37
38
#include "py/objstr.h"
#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/builtin.h"
#include "py/stream.h"
#include "py/pfenv.h"
39

40
#if MICROPY_PY_BUILTINS_FLOAT
41
42
43
#include <math.h>
#endif

Damien George's avatar
Damien George committed
44
45
46
// args[0] is function from class body
// args[1] is class name
// args[2:] are base objects
47
STATIC mp_obj_t mp_builtin___build_class__(mp_uint_t n_args, const mp_obj_t *args) {
Damien George's avatar
Damien George committed
48
49
    assert(2 <= n_args);

50
51
    // set the new classes __locals__ object
    mp_obj_dict_t *old_locals = mp_locals_get();
52
    mp_obj_t class_locals = mp_obj_new_dict(0);
53
    mp_locals_set(class_locals);
54
55

    // call the class code
56
    mp_obj_t cell = mp_call_function_0(args[0]);
57
58

    // restore old __locals__ object
Damien George's avatar
Damien George committed
59
    mp_locals_set(old_locals);
60

Damien George's avatar
Damien George committed
61
62
63
64
    // get the class type (meta object) from the base objects
    mp_obj_t meta;
    if (n_args == 2) {
        // no explicit bases, so use 'type'
65
        meta = (mp_obj_t)&mp_type_type;
Damien George's avatar
Damien George committed
66
67
68
69
70
71
72
73
74
    } 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];
75
    meta_args[0] = args[1]; // class name
Damien George's avatar
Damien George committed
76
    meta_args[1] = mp_obj_new_tuple(n_args - 2, args + 2); // tuple of bases
77
    meta_args[2] = class_locals; // dict of members
Damien George's avatar
Damien George committed
78
    mp_obj_t new_class = mp_call_function_n_kw(meta, 3, 0, meta_args);
Damien George's avatar
Damien George committed
79
80
81
82
83
84
85

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

    return new_class;
86
}
Damien George's avatar
Damien George committed
87
88
MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj, 2, mp_builtin___build_class__);

89
STATIC mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
90
91
    if (0) {
        // dummy
92
#if MICROPY_PY_BUILTINS_FLOAT
93
    } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_float)) {
94
        mp_float_t value = mp_obj_float_get(o_in);
95
        // TODO check for NaN etc
96
97
        if (value < 0) {
            return mp_obj_new_float(-value);
98
        } else {
99
            return o_in;
100
        }
101
#if MICROPY_PY_BUILTINS_COMPLEX
102
    } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_complex)) {
103
104
        mp_float_t real, imag;
        mp_obj_complex_get(o_in, &real, &imag);
105
        return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag));
106
#endif
107
108
#endif
    } else {
109
110
        // this will raise a TypeError if the argument is not integral
        return mp_obj_int_abs(o_in);
111
112
    }
}
113
114
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_abs_obj, mp_builtin_abs);

115
STATIC mp_obj_t mp_builtin_all(mp_obj_t o_in) {
Damien George's avatar
Damien George committed
116
    mp_obj_t iterable = mp_getiter(o_in);
117
    mp_obj_t item;
118
    while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
Damien George's avatar
Damien George committed
119
        if (!mp_obj_is_true(item)) {
120
            return mp_const_false;
121
122
        }
    }
123
    return mp_const_true;
124
}
125
126
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_all_obj, mp_builtin_all);

127
STATIC mp_obj_t mp_builtin_any(mp_obj_t o_in) {
Damien George's avatar
Damien George committed
128
    mp_obj_t iterable = mp_getiter(o_in);
129
    mp_obj_t item;
130
    while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
Damien George's avatar
Damien George committed
131
        if (mp_obj_is_true(item)) {
132
            return mp_const_true;
133
134
        }
    }
135
    return mp_const_false;
136
}
137
138
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_any_obj, mp_builtin_any);

139
140
STATIC mp_obj_t mp_builtin_bin(mp_obj_t o_in) {
    mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_b_brace_close_), o_in };
141
    return mp_obj_str_format(MP_ARRAY_SIZE(args), args, NULL);
142
143
144
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_bin_obj, mp_builtin_bin);

145
STATIC mp_obj_t mp_builtin_callable(mp_obj_t o_in) {
146
147
    if (mp_obj_is_callable(o_in)) {
        return mp_const_true;
148
    } else {
149
        return mp_const_false;
150
151
    }
}
152
153
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_callable_obj, mp_builtin_callable);

154
STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
155
    #if MICROPY_PY_BUILTINS_STR_UNICODE
156
    mp_uint_t c = mp_obj_get_int(o_in);
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
    char str[4];
    int len = 0;
    if (c < 0x80) {
        *str = c; len = 1;
    } else if (c < 0x800) {
        str[0] = (c >> 6) | 0xC0;
        str[1] = (c & 0x3F) | 0x80;
        len = 2;
    } else if (c < 0x10000) {
        str[0] = (c >> 12) | 0xE0;
        str[1] = ((c >> 6) & 0x3F) | 0x80;
        str[2] = (c & 0x3F) | 0x80;
        len = 3;
    } else if (c < 0x110000) {
        str[0] = (c >> 18) | 0xF0;
        str[1] = ((c >> 12) & 0x3F) | 0x80;
        str[2] = ((c >> 6) & 0x3F) | 0x80;
        str[3] = (c & 0x3F) | 0x80;
        len = 4;
176
    } else {
177
        nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)"));
178
    }
179
    return mp_obj_new_str(str, len, true);
180
    #else
181
    mp_int_t ord = mp_obj_get_int(o_in);
182
    if (0 <= ord && ord <= 0xff) {
183
184
185
        char str[1] = {ord};
        return mp_obj_new_str(str, 1, true);
    } else {
186
        nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(256)"));
187
188
    }
    #endif
189
}
190
191
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_chr_obj, mp_builtin_chr);

192
STATIC mp_obj_t mp_builtin_dir(mp_uint_t n_args, const mp_obj_t *args) {
193
194
    // TODO make this function more general and less of a hack

195
    mp_obj_dict_t *dict = NULL;
196
197
    if (n_args == 0) {
        // make a list of names in the local name space
198
        dict = mp_locals_get();
199
200
    } else { // n_args == 1
        // make a list of names in the given object
Damien George's avatar
Damien George committed
201
        if (MP_OBJ_IS_TYPE(args[0], &mp_type_module)) {
202
            dict = mp_obj_module_get_globals(args[0]);
Damien George's avatar
Damien George committed
203
204
205
206
207
208
209
        } else {
            mp_obj_type_t *type;
            if (MP_OBJ_IS_TYPE(args[0], &mp_type_type)) {
                type = args[0];
            } else {
                type = mp_obj_get_type(args[0]);
            }
210
            if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) {
211
                dict = type->locals_dict;
Damien George's avatar
Damien George committed
212
            }
213
        }
214
215
216
    }

    mp_obj_t dir = mp_obj_new_list(0, NULL);
217
    if (dict != NULL) {
218
        for (mp_uint_t i = 0; i < dict->map.alloc; i++) {
219
220
            if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
                mp_obj_list_append(dir, dict->map.table[i].key);
221
222
223
            }
        }
    }
224

225
226
227
228
    return dir;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_dir_obj, 0, 1, mp_builtin_dir);

229
STATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
230
    // TODO handle big int
231
    if (MP_OBJ_IS_SMALL_INT(o1_in) && MP_OBJ_IS_SMALL_INT(o2_in)) {
232
233
        mp_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in);
        mp_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in);
234
        if (i2 == 0) {
235
            #if MICROPY_PY_BUILTINS_FLOAT
236
            zero_division_error:
237
            #endif
238
239
            nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "division by zero"));
        }
240
        mp_obj_t args[2];
241
242
        args[0] = MP_OBJ_NEW_SMALL_INT(mp_small_int_floor_divide(i1, i2));
        args[1] = MP_OBJ_NEW_SMALL_INT(mp_small_int_modulo(i1, i2));
243
        return mp_obj_new_tuple(2, args);
244
    #if MICROPY_PY_BUILTINS_FLOAT
245
246
247
248
249
250
251
252
253
254
255
256
    } else if (MP_OBJ_IS_TYPE(o1_in, &mp_type_float) || MP_OBJ_IS_TYPE(o2_in, &mp_type_float)) {
        mp_float_t f1 = mp_obj_get_float(o1_in);
        mp_float_t f2 = mp_obj_get_float(o2_in);
        if (f2 == 0.0) {
            goto zero_division_error;
        }
        mp_obj_float_divmod(&f1, &f2);
        mp_obj_t tuple[2] = {
            mp_obj_new_float(f1),
            mp_obj_new_float(f2),
        };
        return mp_obj_new_tuple(2, tuple);
257
    #endif
258
    } else {
259
260
261
262
263
264
265
266
        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
                "unsupported operand type(s) for divmod()"));
        } else {
            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
                "unsupported operand type(s) for divmod(): '%s' and '%s'",
                mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in)));
        }
267
268
    }
}
269
270
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_divmod_obj, mp_builtin_divmod);

271
STATIC mp_obj_t mp_builtin_hash(mp_obj_t o_in) {
272
    // TODO hash will generally overflow small integer; can we safely truncate it?
273
    return mp_obj_new_int(mp_obj_hash(o_in));
274
}
275
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hash_obj, mp_builtin_hash);
276

Damien George's avatar
Damien George committed
277
STATIC mp_obj_t mp_builtin_hex(mp_obj_t o_in) {
278
    return mp_binary_op(MP_BINARY_OP_MODULO, MP_OBJ_NEW_QSTR(MP_QSTR__percent__hash_x), o_in);
Damien George's avatar
Damien George committed
279
280
281
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hex_obj, mp_builtin_hex);

282
STATIC mp_obj_t mp_builtin_iter(mp_obj_t o_in) {
Damien George's avatar
Damien George committed
283
    return mp_getiter(o_in);
284
}
285
286
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter);

287
STATIC mp_obj_t mp_builtin_min_max(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs, mp_uint_t op) {
288
289
    mp_map_elem_t *key_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_key), MP_MAP_LOOKUP);
    mp_obj_t key_fn = key_elem == NULL ? MP_OBJ_NULL : key_elem->value;
290
291
    if (n_args == 1) {
        // given an iterable
Damien George's avatar
Damien George committed
292
        mp_obj_t iterable = mp_getiter(args[0]);
293
294
        mp_obj_t best_key = MP_OBJ_NULL;
        mp_obj_t best_obj = MP_OBJ_NULL;
295
        mp_obj_t item;
296
        while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
297
298
299
300
            mp_obj_t key = key_fn == MP_OBJ_NULL ? item : mp_call_function_1(key_fn, item);
            if (best_obj == MP_OBJ_NULL || (mp_binary_op(op, key, best_key) == mp_const_true)) {
                best_key = key;
                best_obj = item;
301
            }
302
        }
303
304
        if (best_obj == MP_OBJ_NULL) {
            nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "arg is an empty sequence"));
305
        }
306
        return best_obj;
307
    } else {
308
        // given many args
309
310
311
312
313
314
315
        mp_obj_t best_key = MP_OBJ_NULL;
        mp_obj_t best_obj = MP_OBJ_NULL;
        for (mp_uint_t i = 0; i < n_args; i++) {
            mp_obj_t key = key_fn == MP_OBJ_NULL ? args[i] : mp_call_function_1(key_fn, args[i]);
            if (best_obj == MP_OBJ_NULL || (mp_binary_op(op, key, best_key) == mp_const_true)) {
                best_key = key;
                best_obj = args[i];
316
317
            }
        }
318
        return best_obj;
319
320
321
    }
}

322
STATIC mp_obj_t mp_builtin_max(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
323
    return mp_builtin_min_max(n_args, args, kwargs, MP_BINARY_OP_MORE);
324
}
325
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_max_obj, 1, mp_builtin_max);
326

327
STATIC mp_obj_t mp_builtin_min(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
328
329
330
    return mp_builtin_min_max(n_args, args, kwargs, MP_BINARY_OP_LESS);
}
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_min_obj, 1, mp_builtin_min);
331

332
STATIC mp_obj_t mp_builtin_next(mp_obj_t o) {
Damien George's avatar
Damien George committed
333
    mp_obj_t ret = mp_iternext_allow_raise(o);
334
    if (ret == MP_OBJ_STOP_ITERATION) {
335
        nlr_raise(mp_obj_new_exception(&mp_type_StopIteration));
336
337
338
    } else {
        return ret;
    }
339
340
341
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_next_obj, mp_builtin_next);

342
343
344
345
346
STATIC mp_obj_t mp_builtin_oct(mp_obj_t o_in) {
    return mp_binary_op(MP_BINARY_OP_MODULO, MP_OBJ_NEW_QSTR(MP_QSTR__percent__hash_o), o_in);
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_oct_obj, mp_builtin_oct);

347
STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
348
    mp_uint_t len;
349
    const char *str = mp_obj_str_get_data(o_in, &len);
350
    #if MICROPY_PY_BUILTINS_STR_UNICODE
351
352
    len = unichar_charlen(str, len);
    if (len == 1) {
353
        if (MP_OBJ_IS_STR(o_in) && UTF8_IS_NONASCII(*str)) {
354
355
            mp_int_t ord = *str++ & 0x7F;
            for (mp_int_t mask = 0x40; ord & mask; mask >>= 1) {
356
357
358
359
360
361
362
363
364
                ord &= ~mask;
            }
            while (UTF8_IS_CONT(*str)) {
                ord = (ord << 6) | (*str++ & 0x3F);
            }
            return mp_obj_new_int(ord);
        } else {
            return mp_obj_new_int(((const byte*)str)[0]);
        }
365
    }
366
367
368
369
370
371
    #else
    if (len == 1) {
        // don't sign extend when converting to ord
        return mp_obj_new_int(((const byte*)str)[0]);
    }
    #endif
372
373
374
375
376
377
378
379

    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
            "ord expects a character"));
    } else {
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
            "ord() expected a character, but string of length %d found", len));
    }
380
}
381
382
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_ord_obj, mp_builtin_ord);

383
STATIC mp_obj_t mp_builtin_pow(mp_uint_t n_args, const mp_obj_t *args) {
384
    assert(2 <= n_args && n_args <= 3);
385
    switch (n_args) {
Damien George's avatar
Damien George committed
386
387
        case 2: return mp_binary_op(MP_BINARY_OP_POWER, args[0], args[1]);
        default: return mp_binary_op(MP_BINARY_OP_MODULO, mp_binary_op(MP_BINARY_OP_POWER, args[0], args[1]), args[2]); // TODO optimise...
388
389
    }
}
390
391
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj, 2, 3, mp_builtin_pow);

392
STATIC mp_obj_t mp_builtin_print(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
393
394
395
    mp_map_elem_t *sep_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_MAP_LOOKUP);
    mp_map_elem_t *end_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_MAP_LOOKUP);
    const char *sep_data = " ";
396
    mp_uint_t sep_len = 1;
397
    const char *end_data = "\n";
398
    mp_uint_t end_len = 1;
399
400
401
402
403
404
    if (sep_elem != NULL && sep_elem->value != mp_const_none) {
        sep_data = mp_obj_str_get_data(sep_elem->value, &sep_len);
    }
    if (end_elem != NULL && end_elem->value != mp_const_none) {
        end_data = mp_obj_str_get_data(end_elem->value, &end_len);
    }
405
    #if MICROPY_PY_IO
406
    extern mp_uint_t mp_sys_stdout_obj; // type is irrelevant, just need pointer
407
408
409
410
411
412
413
414
    mp_obj_t stream_obj = &mp_sys_stdout_obj;
    mp_map_elem_t *file_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_file), MP_MAP_LOOKUP);
    if (file_elem != NULL && file_elem->value != mp_const_none) {
        stream_obj = file_elem->value;
    }

    pfenv_t pfenv;
    pfenv.data = stream_obj;
415
    pfenv.print_strn = (void (*)(void *, const char *, mp_uint_t))mp_stream_write;
416
    #endif
417
    for (mp_uint_t i = 0; i < n_args; i++) {
418
        if (i > 0) {
419
420
421
            #if MICROPY_PY_IO
            mp_stream_write(stream_obj, sep_data, sep_len);
            #else
422
            printf("%.*s", (int)sep_len, sep_data);
423
            #endif
424
        }
425
426
427
        #if MICROPY_PY_IO
        mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))pfenv_printf, &pfenv, args[i], PRINT_STR);
        #else
428
        mp_obj_print(args[i], PRINT_STR);
429
        #endif
430
    }
431
432
433
    #if MICROPY_PY_IO
    mp_stream_write(stream_obj, end_data, end_len);
    #else
434
    printf("%.*s", (int)end_len, end_data);
435
    #endif
436
    return mp_const_none;
437
}
438
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_print_obj, 0, mp_builtin_print);
439

440
441
STATIC mp_obj_t mp_builtin___repl_print__(mp_obj_t o) {
    if (o != mp_const_none) {
442
443
444
445
446
447
448
449
450
451
452
        #if MICROPY_PY_IO
        extern mp_uint_t mp_sys_stdout_obj; // type is irrelevant, just need pointer
        pfenv_t pfenv;
        pfenv.data = &mp_sys_stdout_obj;
        pfenv.print_strn = (void (*)(void *, const char *, mp_uint_t))mp_stream_write;
        mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))pfenv_printf, &pfenv, o, PRINT_REPR);
        mp_stream_write(&mp_sys_stdout_obj, "\n", 1);
        #else
        mp_obj_print(o, PRINT_REPR);
        printf("\n");
        #endif
453
454
455
456
457
    }
    return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin___repl_print___obj, mp_builtin___repl_print__);

458
STATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) {
459
460
461
462
    vstr_t vstr;
    vstr_init(&vstr, 16);
    mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))vstr_printf, &vstr, o_in, PRINT_REPR);
    return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
Damien George's avatar
Damien George committed
463
464
465
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr);

466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
STATIC mp_obj_t mp_builtin_round(mp_obj_t o_in) {
    // TODO support second arg
    if (MP_OBJ_IS_INT(o_in)) {
        return o_in;
    }
#if MICROPY_PY_BUILTINS_FLOAT
    mp_float_t val = mp_obj_get_float(o_in);
    mp_float_t rounded = MICROPY_FLOAT_C_FUN(round)(val);
    mp_int_t r = rounded;
    // make rounded value even if it was halfway between ints
    if (val - rounded == 0.5) {
        r = (r + 1) & (~1);
    } else if (val - rounded == -0.5) {
        r &= ~1;
    }
#else
    mp_int_t r = mp_obj_get_int(o_in);
#endif
    return mp_obj_new_int(r);
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_round_obj, mp_builtin_round);

488
STATIC mp_obj_t mp_builtin_sum(mp_uint_t n_args, const mp_obj_t *args) {
489
    assert(1 <= n_args && n_args <= 2);
490
    mp_obj_t value;
491
    switch (n_args) {
492
        case 1: value = MP_OBJ_NEW_SMALL_INT(0); break;
493
        default: value = args[1]; break;
494
    }
Damien George's avatar
Damien George committed
495
    mp_obj_t iterable = mp_getiter(args[0]);
496
    mp_obj_t item;
497
    while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
Damien George's avatar
Damien George committed
498
        value = mp_binary_op(MP_BINARY_OP_ADD, value, item);
499
500
501
    }
    return value;
}
502
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
503

504
STATIC mp_obj_t mp_builtin_sorted(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
505
506
    assert(n_args >= 1);
    if (n_args > 1) {
507
        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
John R. Lenton's avatar
sorted    
John R. Lenton committed
508
509
                                          "must use keyword argument for key function"));
    }
510
    mp_obj_t self = mp_type_list.make_new((mp_obj_t)&mp_type_list, 1, 0, args);
511
    mp_obj_list_sort(1, &self, kwargs);
John R. Lenton's avatar
sorted    
John R. Lenton committed
512
513
514

    return self;
}
515
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, 1, mp_builtin_sorted);
516

517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
// See mp_load_attr() if making any changes
STATIC inline mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t defval) {
    mp_obj_t dest[2];
    // use load_method, raising or not raising exception
    ((defval == MP_OBJ_NULL) ? mp_load_method : mp_load_method_maybe)(base, attr, dest);
    if (dest[0] == MP_OBJ_NULL) {
        return defval;
    } else if (dest[1] == MP_OBJ_NULL) {
        // load_method returned just a normal attribute
        return dest[0];
    } else {
        // load_method returned a method, so build a bound method object
        return mp_obj_new_bound_meth(dest[0], dest[1]);
    }
}

533
STATIC mp_obj_t mp_builtin_getattr(mp_uint_t n_args, const mp_obj_t *args) {
534
535
536
537
    mp_obj_t defval = MP_OBJ_NULL;
    if (n_args > 2) {
        defval = args[2];
    }
stijn's avatar
stijn committed
538
    return mp_load_attr_default(args[0], mp_obj_str_get_qstr(args[1]), defval);
539
}
540
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj, 2, 3, mp_builtin_getattr);
541

stijn's avatar
stijn committed
542
543
544
545
546
547
STATIC mp_obj_t mp_builtin_setattr(mp_obj_t base, mp_obj_t attr, mp_obj_t value) {
    mp_store_attr(base, mp_obj_str_get_qstr(attr), value);
    return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(mp_builtin_setattr_obj, mp_builtin_setattr);

548
549
550
551
STATIC mp_obj_t mp_builtin_hasattr(mp_obj_t object_in, mp_obj_t attr_in) {
    assert(MP_OBJ_IS_QSTR(attr_in));

    mp_obj_t dest[2];
552
    // TODO: https://docs.python.org/3/library/functions.html?highlight=hasattr#hasattr
553
554
555
556
557
558
559
560
561
    // explicitly says "This is implemented by calling getattr(object, name) and seeing
    // whether it raises an AttributeError or not.", so we should explicitly wrap this
    // in nlr_push and handle exception.
    mp_load_method_maybe(object_in, MP_OBJ_QSTR_VALUE(attr_in), dest);

    return MP_BOOL(dest[0] != MP_OBJ_NULL);
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_hasattr_obj, mp_builtin_hasattr);

562
// These are defined in terms of MicroPython API functions right away
563
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_id_obj, mp_obj_id);
564
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_len_obj, mp_obj_len);
565
566
MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_globals_obj, mp_globals_get);
MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_locals_obj, mp_locals_get);
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588

STATIC const mp_map_elem_t mp_module_builtins_globals_table[] = {
    // built-in core functions
    { MP_OBJ_NEW_QSTR(MP_QSTR___build_class__), (mp_obj_t)&mp_builtin___build_class___obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR___import__), (mp_obj_t)&mp_builtin___import___obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR___repl_print__), (mp_obj_t)&mp_builtin___repl_print___obj },

    // built-in types
    { MP_OBJ_NEW_QSTR(MP_QSTR_bool), (mp_obj_t)&mp_type_bool },
    { MP_OBJ_NEW_QSTR(MP_QSTR_bytes), (mp_obj_t)&mp_type_bytes },
#if MICROPY_PY_BUILTINS_BYTEARRAY
    { MP_OBJ_NEW_QSTR(MP_QSTR_bytearray), (mp_obj_t)&mp_type_bytearray },
#endif
#if MICROPY_PY_BUILTINS_COMPLEX
    { MP_OBJ_NEW_QSTR(MP_QSTR_complex), (mp_obj_t)&mp_type_complex },
#endif
    { MP_OBJ_NEW_QSTR(MP_QSTR_dict), (mp_obj_t)&mp_type_dict },
    { MP_OBJ_NEW_QSTR(MP_QSTR_enumerate), (mp_obj_t)&mp_type_enumerate },
    { MP_OBJ_NEW_QSTR(MP_QSTR_filter), (mp_obj_t)&mp_type_filter },
#if MICROPY_PY_BUILTINS_FLOAT
    { MP_OBJ_NEW_QSTR(MP_QSTR_float), (mp_obj_t)&mp_type_float },
#endif
589
#if MICROPY_PY_BUILTINS_SET && MICROPY_PY_BUILTINS_FROZENSET
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
    { MP_OBJ_NEW_QSTR(MP_QSTR_frozenset), (mp_obj_t)&mp_type_frozenset },
#endif
    { MP_OBJ_NEW_QSTR(MP_QSTR_int), (mp_obj_t)&mp_type_int },
    { MP_OBJ_NEW_QSTR(MP_QSTR_list), (mp_obj_t)&mp_type_list },
    { MP_OBJ_NEW_QSTR(MP_QSTR_map), (mp_obj_t)&mp_type_map },
#if MICROPY_PY_BUILTINS_MEMORYVIEW
    { MP_OBJ_NEW_QSTR(MP_QSTR_memoryview), (mp_obj_t)&mp_type_memoryview },
#endif
    { MP_OBJ_NEW_QSTR(MP_QSTR_object), (mp_obj_t)&mp_type_object },
#if MICROPY_PY_BUILTINS_PROPERTY
    { MP_OBJ_NEW_QSTR(MP_QSTR_property), (mp_obj_t)&mp_type_property },
#endif
    { MP_OBJ_NEW_QSTR(MP_QSTR_range), (mp_obj_t)&mp_type_range },
    { MP_OBJ_NEW_QSTR(MP_QSTR_reversed), (mp_obj_t)&mp_type_reversed },
#if MICROPY_PY_BUILTINS_SET
    { MP_OBJ_NEW_QSTR(MP_QSTR_set), (mp_obj_t)&mp_type_set },
#endif
    { MP_OBJ_NEW_QSTR(MP_QSTR_str), (mp_obj_t)&mp_type_str },
    { MP_OBJ_NEW_QSTR(MP_QSTR_super), (mp_obj_t)&mp_type_super },
    { MP_OBJ_NEW_QSTR(MP_QSTR_tuple), (mp_obj_t)&mp_type_tuple },
    { MP_OBJ_NEW_QSTR(MP_QSTR_type), (mp_obj_t)&mp_type_type },
    { MP_OBJ_NEW_QSTR(MP_QSTR_zip), (mp_obj_t)&mp_type_zip },

    { MP_OBJ_NEW_QSTR(MP_QSTR_classmethod), (mp_obj_t)&mp_type_classmethod },
    { MP_OBJ_NEW_QSTR(MP_QSTR_staticmethod), (mp_obj_t)&mp_type_staticmethod },

    // built-in objects
    { MP_OBJ_NEW_QSTR(MP_QSTR_Ellipsis), (mp_obj_t)&mp_const_ellipsis_obj },

    // built-in user functions
    { MP_OBJ_NEW_QSTR(MP_QSTR_abs), (mp_obj_t)&mp_builtin_abs_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_all), (mp_obj_t)&mp_builtin_all_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&mp_builtin_any_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_bin), (mp_obj_t)&mp_builtin_bin_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_callable), (mp_obj_t)&mp_builtin_callable_obj },
#if MICROPY_PY_BUILTINS_COMPILE
    { MP_OBJ_NEW_QSTR(MP_QSTR_compile), (mp_obj_t)&mp_builtin_compile_obj },
#endif
    { MP_OBJ_NEW_QSTR(MP_QSTR_chr), (mp_obj_t)&mp_builtin_chr_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_dir), (mp_obj_t)&mp_builtin_dir_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_divmod), (mp_obj_t)&mp_builtin_divmod_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_eval), (mp_obj_t)&mp_builtin_eval_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_exec), (mp_obj_t)&mp_builtin_exec_obj },
633
634
635
#if MICROPY_PY_BUILTINS_EXECFILE
    { MP_OBJ_NEW_QSTR(MP_QSTR_execfile), (mp_obj_t)&mp_builtin_execfile_obj },
#endif
636
    { MP_OBJ_NEW_QSTR(MP_QSTR_getattr), (mp_obj_t)&mp_builtin_getattr_obj },
stijn's avatar
stijn committed
637
    { MP_OBJ_NEW_QSTR(MP_QSTR_setattr), (mp_obj_t)&mp_builtin_setattr_obj },
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
    { MP_OBJ_NEW_QSTR(MP_QSTR_globals), (mp_obj_t)&mp_builtin_globals_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_hasattr), (mp_obj_t)&mp_builtin_hasattr_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_hash), (mp_obj_t)&mp_builtin_hash_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_hex), (mp_obj_t)&mp_builtin_hex_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_id), (mp_obj_t)&mp_builtin_id_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_isinstance), (mp_obj_t)&mp_builtin_isinstance_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_issubclass), (mp_obj_t)&mp_builtin_issubclass_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_iter), (mp_obj_t)&mp_builtin_iter_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_len), (mp_obj_t)&mp_builtin_len_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_locals), (mp_obj_t)&mp_builtin_locals_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_max), (mp_obj_t)&mp_builtin_max_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_min), (mp_obj_t)&mp_builtin_min_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_next), (mp_obj_t)&mp_builtin_next_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_oct), (mp_obj_t)&mp_builtin_oct_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_ord), (mp_obj_t)&mp_builtin_ord_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_pow), (mp_obj_t)&mp_builtin_pow_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_print), (mp_obj_t)&mp_builtin_print_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_repr), (mp_obj_t)&mp_builtin_repr_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_round), (mp_obj_t)&mp_builtin_round_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_sorted), (mp_obj_t)&mp_builtin_sorted_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_sum), (mp_obj_t)&mp_builtin_sum_obj },

    // built-in exceptions
    { MP_OBJ_NEW_QSTR(MP_QSTR_BaseException), (mp_obj_t)&mp_type_BaseException },
    { MP_OBJ_NEW_QSTR(MP_QSTR_ArithmeticError), (mp_obj_t)&mp_type_ArithmeticError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_AssertionError), (mp_obj_t)&mp_type_AssertionError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_AttributeError), (mp_obj_t)&mp_type_AttributeError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_EOFError), (mp_obj_t)&mp_type_EOFError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_Exception), (mp_obj_t)&mp_type_Exception },
    { MP_OBJ_NEW_QSTR(MP_QSTR_GeneratorExit), (mp_obj_t)&mp_type_GeneratorExit },
    { MP_OBJ_NEW_QSTR(MP_QSTR_ImportError), (mp_obj_t)&mp_type_ImportError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_IndentationError), (mp_obj_t)&mp_type_IndentationError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_IndexError), (mp_obj_t)&mp_type_IndexError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_KeyError), (mp_obj_t)&mp_type_KeyError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_LookupError), (mp_obj_t)&mp_type_LookupError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_MemoryError), (mp_obj_t)&mp_type_MemoryError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_NameError), (mp_obj_t)&mp_type_NameError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_NotImplementedError), (mp_obj_t)&mp_type_NotImplementedError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_OSError), (mp_obj_t)&mp_type_OSError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_OverflowError), (mp_obj_t)&mp_type_OverflowError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_RuntimeError), (mp_obj_t)&mp_type_RuntimeError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_StopIteration), (mp_obj_t)&mp_type_StopIteration },
    { MP_OBJ_NEW_QSTR(MP_QSTR_SyntaxError), (mp_obj_t)&mp_type_SyntaxError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_SystemExit), (mp_obj_t)&mp_type_SystemExit },
    { MP_OBJ_NEW_QSTR(MP_QSTR_TypeError), (mp_obj_t)&mp_type_TypeError },
Paul Sokolovsky's avatar
Paul Sokolovsky committed
683
684
685
    #if MICROPY_PY_BUILTINS_STR_UNICODE
    { MP_OBJ_NEW_QSTR(MP_QSTR_UnicodeError), (mp_obj_t)&mp_type_UnicodeError },
    #endif
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
    { MP_OBJ_NEW_QSTR(MP_QSTR_ValueError), (mp_obj_t)&mp_type_ValueError },
    { MP_OBJ_NEW_QSTR(MP_QSTR_ZeroDivisionError), (mp_obj_t)&mp_type_ZeroDivisionError },
    // Somehow CPython managed to have OverflowError not inherit from ValueError ;-/
    // TODO: For MICROPY_CPYTHON_COMPAT==0 use ValueError to avoid exc proliferation

    // Extra builtins as defined by a port
    MICROPY_PORT_BUILTINS
};

MP_DEFINE_CONST_DICT(mp_module_builtins_globals, mp_module_builtins_globals_table);

const mp_obj_module_t mp_module_builtins = {
    .base = { &mp_type_module },
    .name = MP_QSTR_builtins,
    .globals = (mp_obj_dict_t*)&mp_module_builtins_globals,
};