Branch data Line data Source code
1 : : /*
2 : : * This file is part of the MicroPython project, http://micropython.org/
3 : : *
4 : : * The MIT License (MIT)
5 : : *
6 : : * Copyright (c) 2013, 2014 Damien P. George
7 : : * Copyright (c) 2014-2018 Paul Sokolovsky
8 : : *
9 : : * Permission is hereby granted, free of charge, to any person obtaining a copy
10 : : * of this software and associated documentation files (the "Software"), to deal
11 : : * in the Software without restriction, including without limitation the rights
12 : : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 : : * copies of the Software, and to permit persons to whom the Software is
14 : : * furnished to do so, subject to the following conditions:
15 : : *
16 : : * The above copyright notice and this permission notice shall be included in
17 : : * all copies or substantial portions of the Software.
18 : : *
19 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 : : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 : : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 : : * THE SOFTWARE.
26 : : */
27 : :
28 : : #include <assert.h>
29 : : #include <stdarg.h>
30 : : #include <stdio.h>
31 : : #include <string.h>
32 : : #include <unistd.h>
33 : :
34 : : #include "py/parsenum.h"
35 : : #include "py/compile.h"
36 : : #include "py/objstr.h"
37 : : #include "py/objtuple.h"
38 : : #include "py/objlist.h"
39 : : #include "py/objtype.h"
40 : : #include "py/objmodule.h"
41 : : #include "py/objgenerator.h"
42 : : #include "py/smallint.h"
43 : : #include "py/stream.h"
44 : : #include "py/runtime.h"
45 : : #include "py/builtin.h"
46 : : #include "py/cstack.h"
47 : : #include "py/gc.h"
48 : :
49 : : #if MICROPY_VFS_ROM && MICROPY_VFS_ROM_IOCTL
50 : : #include "extmod/vfs.h"
51 : : #endif
52 : :
53 : : #if MICROPY_DEBUG_VERBOSE // print debugging info
54 : : #define DEBUG_PRINT (1)
55 : : #define DEBUG_printf DEBUG_printf
56 : : #define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__)
57 : : #else // don't print debugging info
58 : : #define DEBUG_printf(...) (void)0
59 : : #define DEBUG_OP_printf(...) (void)0
60 : : #endif
61 : :
62 : : const mp_obj_module_t mp_module___main__ = {
63 : : .base = { &mp_type_module },
64 : : .globals = (mp_obj_dict_t *)&MP_STATE_VM(dict_main),
65 : : };
66 : :
67 : : MP_REGISTER_MODULE(MP_QSTR___main__, mp_module___main__);
68 : :
69 : : #define TYPE_HAS_ITERNEXT(type) (type->flags & (MP_TYPE_FLAG_ITER_IS_ITERNEXT | MP_TYPE_FLAG_ITER_IS_CUSTOM | MP_TYPE_FLAG_ITER_IS_STREAM))
70 : :
71 : 3448 : void mp_init(void) {
72 : 3448 : qstr_init();
73 : :
74 : : // no pending exceptions to start with
75 : 3448 : MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL;
76 : : #if MICROPY_ENABLE_SCHEDULER
77 : : // no pending callbacks to start with
78 : 3448 : MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
79 : : #if MICROPY_SCHEDULER_STATIC_NODES
80 : : if (MP_STATE_VM(sched_head) != NULL) {
81 : : // pending callbacks are on the list, eg from before a soft reset
82 : : MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
83 : : }
84 : : #endif
85 : 3448 : MP_STATE_VM(sched_idx) = 0;
86 : 3448 : MP_STATE_VM(sched_len) = 0;
87 : : #endif
88 : :
89 : : #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
90 : 3448 : mp_init_emergency_exception_buf();
91 : : #endif
92 : :
93 : : #if MICROPY_KBD_EXCEPTION
94 : : // initialise the exception object for raising KeyboardInterrupt
95 : 3448 : MP_STATE_VM(mp_kbd_exception).base.type = &mp_type_KeyboardInterrupt;
96 : 3448 : MP_STATE_VM(mp_kbd_exception).traceback_alloc = 0;
97 : 3448 : MP_STATE_VM(mp_kbd_exception).traceback_len = 0;
98 : 3448 : MP_STATE_VM(mp_kbd_exception).traceback_data = NULL;
99 : 3448 : MP_STATE_VM(mp_kbd_exception).args = (mp_obj_tuple_t *)&mp_const_empty_tuple_obj;
100 : : #endif
101 : :
102 : : #if MICROPY_ENABLE_COMPILER
103 : : // optimization disabled by default
104 : 3448 : MP_STATE_VM(mp_optimise_value) = 0;
105 : : #if MICROPY_EMIT_NATIVE
106 : 3448 : MP_STATE_VM(default_emit_opt) = MP_EMIT_OPT_NONE;
107 : : #endif
108 : : #endif
109 : :
110 : : // init global module dict
111 : 3448 : mp_obj_dict_init(&MP_STATE_VM(mp_loaded_modules_dict), MICROPY_LOADED_MODULES_DICT_SIZE);
112 : :
113 : : // initialise the __main__ module
114 : 3448 : mp_obj_dict_init(&MP_STATE_VM(dict_main), 1);
115 : 3448 : mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(dict_main)), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
116 : :
117 : : // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
118 : 3448 : mp_locals_set(&MP_STATE_VM(dict_main));
119 : 3448 : mp_globals_set(&MP_STATE_VM(dict_main));
120 : :
121 : : #if MICROPY_CAN_OVERRIDE_BUILTINS
122 : : // start with no extensions to builtins
123 : 3448 : MP_STATE_VM(mp_module_builtins_override_dict) = NULL;
124 : : #endif
125 : :
126 : : #if MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA || MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA
127 : 3448 : MP_STATE_VM(persistent_code_root_pointers) = MP_OBJ_NULL;
128 : : #endif
129 : :
130 : : #if MICROPY_PY_OS_DUPTERM
131 : : for (size_t i = 0; i < MICROPY_PY_OS_DUPTERM; ++i) {
132 : : MP_STATE_VM(dupterm_objs[i]) = MP_OBJ_NULL;
133 : : }
134 : : #endif
135 : :
136 : : #if MICROPY_VFS
137 : : // initialise the VFS sub-system
138 : 3448 : MP_STATE_VM(vfs_cur) = NULL;
139 : 3448 : MP_STATE_VM(vfs_mount_table) = NULL;
140 : : #endif
141 : :
142 : : #if MICROPY_PY_SYS_PATH_ARGV_DEFAULTS
143 : : #if MICROPY_PY_SYS_PATH
144 : : mp_sys_path = mp_obj_new_list(0, NULL);
145 : : mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script)
146 : : #if MICROPY_MODULE_FROZEN
147 : : mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__dot_frozen));
148 : : #endif
149 : : #endif
150 : : #if MICROPY_PY_SYS_ARGV
151 : : mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0);
152 : : #endif
153 : : #endif // MICROPY_PY_SYS_PATH_ARGV_DEFAULTS
154 : :
155 : : #if MICROPY_PY_SYS_ATEXIT
156 : 3448 : MP_STATE_VM(sys_exitfunc) = mp_const_none;
157 : : #endif
158 : :
159 : : #if MICROPY_PY_SYS_PS1_PS2
160 : 3448 : MP_STATE_VM(sys_mutable[MP_SYS_MUTABLE_PS1]) = MP_OBJ_NEW_QSTR(MP_QSTR__gt__gt__gt__space_);
161 : 3448 : MP_STATE_VM(sys_mutable[MP_SYS_MUTABLE_PS2]) = MP_OBJ_NEW_QSTR(MP_QSTR__dot__dot__dot__space_);
162 : : #endif
163 : :
164 : : #if MICROPY_PY_SYS_SETTRACE
165 : : MP_STATE_THREAD(prof_trace_callback) = MP_OBJ_NULL;
166 : : MP_STATE_THREAD(prof_callback_is_executing) = false;
167 : : MP_STATE_THREAD(current_code_state) = NULL;
168 : : #endif
169 : :
170 : : #if MICROPY_PY_SYS_TRACEBACKLIMIT
171 : 3448 : MP_STATE_VM(sys_mutable[MP_SYS_MUTABLE_TRACEBACKLIMIT]) = MP_OBJ_NEW_SMALL_INT(1000);
172 : : #endif
173 : :
174 : : #if MICROPY_PY_BLUETOOTH
175 : : MP_STATE_VM(bluetooth) = MP_OBJ_NULL;
176 : : #endif
177 : :
178 : : #if MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE
179 : : MP_STATE_VM(usbd) = MP_OBJ_NULL;
180 : : #endif
181 : :
182 : : #if MICROPY_PY_THREAD_GIL
183 : : mp_thread_mutex_init(&MP_STATE_VM(gil_mutex));
184 : : #endif
185 : :
186 : : // call port specific initialization if any
187 : : #ifdef MICROPY_PORT_INIT_FUNC
188 : : MICROPY_PORT_INIT_FUNC;
189 : : #endif
190 : :
191 : 3448 : MP_THREAD_GIL_ENTER();
192 : :
193 : : #if MICROPY_VFS_ROM && MICROPY_VFS_ROM_IOCTL
194 : : // Mount ROMFS if it exists.
195 : 3448 : mp_vfs_mount_romfs_protected();
196 : : #endif
197 : 3448 : }
198 : :
199 : 3441 : void mp_deinit(void) {
200 : 3441 : MP_THREAD_GIL_EXIT();
201 : :
202 : : // call port specific deinitialization if any
203 : : #ifdef MICROPY_PORT_DEINIT_FUNC
204 : : MICROPY_PORT_DEINIT_FUNC;
205 : : #endif
206 : 3441 : }
207 : :
208 : 3214 : void mp_globals_locals_set_from_nlr_jump_callback(void *ctx_in) {
209 : 3214 : nlr_jump_callback_node_globals_locals_t *ctx = ctx_in;
210 : 3214 : mp_globals_set(ctx->globals);
211 : 3214 : mp_locals_set(ctx->locals);
212 : 3214 : }
213 : :
214 : 5492 : void mp_call_function_1_from_nlr_jump_callback(void *ctx_in) {
215 : 5492 : nlr_jump_callback_node_call_function_1_t *ctx = ctx_in;
216 : 5492 : ctx->func(ctx->arg);
217 : 5492 : }
218 : :
219 : 36043169 : mp_obj_t MICROPY_WRAP_MP_LOAD_NAME(mp_load_name)(qstr qst) {
220 : : // logic: search locals, globals, builtins
221 : 36043169 : DEBUG_OP_printf("load name %s\n", qstr_str(qst));
222 : : // If we're at the outer scope (locals == globals), dispatch to load_global right away
223 [ + + ]: 72086338 : if (mp_locals_get() != mp_globals_get()) {
224 : 1993 : mp_map_elem_t *elem = mp_map_lookup(&mp_locals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
225 [ + + ]: 1993 : if (elem != NULL) {
226 : 50 : return elem->value;
227 : : }
228 : : }
229 : 36043119 : return mp_load_global(qst);
230 : : }
231 : :
232 : 191311775 : mp_obj_t MICROPY_WRAP_MP_LOAD_GLOBAL(mp_load_global)(qstr qst) {
233 : : // logic: search globals, builtins
234 : 191311775 : DEBUG_OP_printf("load global %s\n", qstr_str(qst));
235 : 191311775 : mp_map_elem_t *elem = mp_map_lookup(&mp_globals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
236 [ + + ]: 191147783 : if (elem == NULL) {
237 : : #if MICROPY_CAN_OVERRIDE_BUILTINS
238 [ + + ]: 1324753 : if (MP_STATE_VM(mp_module_builtins_override_dict) != NULL) {
239 : : // lookup in additional dynamic table of builtins first
240 : 238 : elem = mp_map_lookup(&MP_STATE_VM(mp_module_builtins_override_dict)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
241 [ + + ]: 238 : if (elem != NULL) {
242 : 8 : return elem->value;
243 : : }
244 : : }
245 : : #endif
246 : 1324745 : elem = mp_map_lookup((mp_map_t *)&mp_module_builtins_globals.map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
247 [ + + ]: 1324744 : if (elem == NULL) {
248 : : #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
249 : : mp_raise_msg(&mp_type_NameError, MP_ERROR_TEXT("name not defined"));
250 : : #else
251 : 200 : mp_raise_msg_varg(&mp_type_NameError, MP_ERROR_TEXT("name '%q' isn't defined"), qst);
252 : : #endif
253 : : }
254 : : }
255 : 191147574 : return elem->value;
256 : : }
257 : :
258 : 1741 : mp_obj_t mp_load_build_class(void) {
259 : 1741 : DEBUG_OP_printf("load_build_class\n");
260 : : #if MICROPY_CAN_OVERRIDE_BUILTINS
261 [ + + ]: 1741 : if (MP_STATE_VM(mp_module_builtins_override_dict) != NULL) {
262 : : // lookup in additional dynamic table of builtins first
263 : 34 : mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_VM(mp_module_builtins_override_dict)->map, MP_OBJ_NEW_QSTR(MP_QSTR___build_class__), MP_MAP_LOOKUP);
264 [ + + ]: 34 : if (elem != NULL) {
265 : 32 : return elem->value;
266 : : }
267 : : }
268 : : #endif
269 : : return MP_OBJ_FROM_PTR(&mp_builtin___build_class___obj);
270 : : }
271 : :
272 : 654334 : void mp_store_name(qstr qst, mp_obj_t obj) {
273 : 654334 : DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qst), obj);
274 : 654334 : mp_obj_dict_store(MP_OBJ_FROM_PTR(mp_locals_get()), MP_OBJ_NEW_QSTR(qst), obj);
275 : 654332 : }
276 : :
277 : 530 : void mp_delete_name(qstr qst) {
278 : 530 : DEBUG_OP_printf("delete name %s\n", qstr_str(qst));
279 : : // TODO convert KeyError to NameError if qst not found
280 : 530 : mp_obj_dict_delete(MP_OBJ_FROM_PTR(mp_locals_get()), MP_OBJ_NEW_QSTR(qst));
281 : 526 : }
282 : :
283 : 308203 : void mp_store_global(qstr qst, mp_obj_t obj) {
284 : 308203 : DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qst), obj);
285 : 308203 : mp_obj_dict_store(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(qst), obj);
286 : 308203 : }
287 : :
288 : 8 : void mp_delete_global(qstr qst) {
289 : 8 : DEBUG_OP_printf("delete global %s\n", qstr_str(qst));
290 : : // TODO convert KeyError to NameError if qst not found
291 : 8 : mp_obj_dict_delete(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(qst));
292 : 4 : }
293 : :
294 : 1275647 : mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) {
295 : 1275647 : DEBUG_OP_printf("unary " UINT_FMT " %q %p\n", op, mp_unary_op_method_name[op], arg);
296 : :
297 [ + + ]: 1275647 : if (op == MP_UNARY_OP_NOT) {
298 : : // "not x" is the negative of whether "x" is true per Python semantics
299 [ + + ]: 866245 : return mp_obj_new_bool(mp_obj_is_true(arg) == 0);
300 [ + + ]: 697333 : } else if (mp_obj_is_small_int(arg)) {
301 : 414379 : mp_int_t val = MP_OBJ_SMALL_INT_VALUE(arg);
302 [ + + + + : 414379 : switch (op) {
+ ]
303 : 8 : case MP_UNARY_OP_BOOL:
304 [ + - ]: 16 : return mp_obj_new_bool(val != 0);
305 : : case MP_UNARY_OP_HASH:
306 : : return arg;
307 : : case MP_UNARY_OP_POSITIVE:
308 : : case MP_UNARY_OP_INT_MAYBE:
309 : : return arg;
310 : 1983 : case MP_UNARY_OP_NEGATIVE:
311 : : // check for overflow
312 [ + + ]: 1983 : if (val == MP_SMALL_INT_MIN) {
313 : 2 : return mp_obj_new_int(-val);
314 : : } else {
315 : 1981 : return MP_OBJ_NEW_SMALL_INT(-val);
316 : : }
317 : 64 : case MP_UNARY_OP_ABS:
318 [ + + ]: 64 : if (val >= 0) {
319 : : return arg;
320 [ + + ]: 34 : } else if (val == MP_SMALL_INT_MIN) {
321 : : // check for overflow
322 : 2 : return mp_obj_new_int(-val);
323 : : } else {
324 : 32 : return MP_OBJ_NEW_SMALL_INT(-val);
325 : : }
326 : 238 : default:
327 [ - + ]: 238 : assert(op == MP_UNARY_OP_INVERT);
328 : 238 : return MP_OBJ_NEW_SMALL_INT(~val);
329 : : }
330 [ + + + + : 282954 : } else if (op == MP_UNARY_OP_HASH && mp_obj_is_str_or_bytes(arg)) {
+ + + + +
+ ]
331 : : // fast path for hashing str/bytes
332 [ + + ]: 97356 : GET_STR_HASH(arg, h);
333 [ + + ]: 97356 : if (h == 0) {
334 [ - + ]: 4 : GET_STR_DATA_LEN(arg, data, len);
335 : 4 : h = qstr_compute_hash(data, len);
336 : : }
337 : 97356 : return MP_OBJ_NEW_SMALL_INT(h);
338 : : } else {
339 : 185598 : const mp_obj_type_t *type = mp_obj_get_type(arg);
340 [ + + ]: 185598 : if (MP_OBJ_TYPE_HAS_SLOT(type, unary_op)) {
341 : 185422 : mp_obj_t result = MP_OBJ_TYPE_GET_SLOT(type, unary_op)(op, arg);
342 [ + + ]: 185414 : if (result != MP_OBJ_NULL) {
343 : : return result;
344 : : }
345 [ + + ]: 176 : } else if (op == MP_UNARY_OP_HASH) {
346 : : // Type doesn't have unary_op so use hash of object instance.
347 : 128 : return MP_OBJ_NEW_SMALL_INT((mp_uint_t)arg);
348 : : }
349 [ + - ]: 152867 : if (op == MP_UNARY_OP_BOOL) {
350 : : // Type doesn't have unary_op (or didn't handle MP_UNARY_OP_BOOL),
351 : : // so is implicitly True as this code path is impossible to reach
352 : : // if arg==mp_const_none.
353 : : return mp_const_true;
354 : : }
355 : 152867 : if (op == MP_UNARY_OP_INT_MAYBE
356 : : #if MICROPY_PY_BUILTINS_FLOAT
357 : : || op == MP_UNARY_OP_FLOAT_MAYBE
358 : : #if MICROPY_PY_BUILTINS_COMPLEX
359 [ + + ]: 152867 : || op == MP_UNARY_OP_COMPLEX_MAYBE
360 : : #endif
361 : : #endif
362 : : ) {
363 : : // These operators may return MP_OBJ_NULL if they are not supported by the type.
364 : : return MP_OBJ_NULL;
365 : : }
366 : : #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
367 : : mp_raise_TypeError(MP_ERROR_TEXT("unsupported type for operator"));
368 : : #else
369 : 72 : mp_raise_msg_varg(&mp_type_TypeError,
370 : 72 : MP_ERROR_TEXT("unsupported type for %q: '%s'"),
371 : 72 : mp_unary_op_method_name[op], mp_obj_get_type_str(arg));
372 : : #endif
373 : : }
374 : : }
375 : :
376 : 78678123 : mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
377 : 78678123 : DEBUG_OP_printf("binary " UINT_FMT " %q %p %p\n", op, mp_binary_op_method_name[op], lhs, rhs);
378 : :
379 : : // TODO correctly distinguish inplace operators for mutable objects
380 : : // lookup logic that CPython uses for +=:
381 : : // check for implemented +=
382 : : // then check for implemented +
383 : : // then check for implemented seq.inplace_concat
384 : : // then check for implemented seq.concat
385 : : // then fail
386 : : // note that list does not implement + or +=, so that inplace_concat is reached first for +=
387 : :
388 : : // deal with is
389 [ + + ]: 78678123 : if (op == MP_BINARY_OP_IS) {
390 [ + + ]: 1154562 : return mp_obj_new_bool(lhs == rhs);
391 : : }
392 : :
393 : : // deal with == and != for all types
394 [ + + ]: 77812418 : if (op == MP_BINARY_OP_EQUAL || op == MP_BINARY_OP_NOT_EQUAL) {
395 : : // mp_obj_equal_not_equal supports a bunch of shortcuts
396 : 459715 : return mp_obj_equal_not_equal(op, lhs, rhs);
397 : : }
398 : :
399 : : // deal with exception_match for all types
400 [ + + ]: 77352703 : if (op == MP_BINARY_OP_EXCEPTION_MATCH) {
401 : : // rhs must be issubclass(rhs, BaseException)
402 [ + + ]: 11559 : if (mp_obj_is_exception_type(rhs)) {
403 [ + + ]: 10797 : if (mp_obj_exception_match(lhs, rhs)) {
404 : : return mp_const_true;
405 : : } else {
406 : 312 : return mp_const_false;
407 : : }
408 [ - + - + : 762 : } else if (mp_obj_is_type(rhs, &mp_type_tuple)) {
- + - + +
+ + - ]
409 : : mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(rhs);
410 [ + + ]: 1348 : for (size_t i = 0; i < tuple->len; i++) {
411 : 1344 : rhs = tuple->items[i];
412 [ + + ]: 1344 : if (!mp_obj_is_exception_type(rhs)) {
413 : 4 : goto unsupported_op;
414 : : }
415 [ + + ]: 1340 : if (mp_obj_exception_match(lhs, rhs)) {
416 : : return mp_const_true;
417 : : }
418 : : }
419 : : return mp_const_false;
420 : : }
421 : 4 : goto unsupported_op;
422 : : }
423 : :
424 [ + + ]: 77341144 : if (mp_obj_is_small_int(lhs)) {
425 : 76607575 : mp_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs);
426 [ + + ]: 76607575 : if (mp_obj_is_small_int(rhs)) {
427 : 76597637 : mp_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs);
428 : : // This is a binary operation: lhs_val op rhs_val
429 : : // We need to be careful to handle overflow; see CERT INT32-C
430 : : // Operations that can overflow:
431 : : // + result always fits in mp_int_t, then handled by SMALL_INT check
432 : : // - result always fits in mp_int_t, then handled by SMALL_INT check
433 : : // * checked explicitly
434 : : // / if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check
435 : : // % if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check
436 : : // << checked explicitly
437 [ + + + + : 76597637 : switch (op) {
+ + + + +
+ + + + +
+ + + + ]
438 : 3662 : case MP_BINARY_OP_OR:
439 : : case MP_BINARY_OP_INPLACE_OR:
440 : 3662 : lhs_val |= rhs_val;
441 : 3662 : break;
442 : 13472746 : case MP_BINARY_OP_XOR:
443 : : case MP_BINARY_OP_INPLACE_XOR:
444 : 13472746 : lhs_val ^= rhs_val;
445 : 13472746 : break;
446 : 6491351 : case MP_BINARY_OP_AND:
447 : : case MP_BINARY_OP_INPLACE_AND:
448 : 6491351 : lhs_val &= rhs_val;
449 : 6491351 : break;
450 : 4684232 : case MP_BINARY_OP_LSHIFT:
451 : : case MP_BINARY_OP_INPLACE_LSHIFT: {
452 [ + + ]: 4684232 : if (rhs_val < 0) {
453 : : // negative shift not allowed
454 : 8 : mp_raise_ValueError(MP_ERROR_TEXT("negative shift count"));
455 [ + + ]: 4684224 : } else if (rhs_val >= (mp_int_t)(sizeof(lhs_val) * MP_BITS_PER_BYTE)
456 [ + + ]: 4683672 : || lhs_val > (MP_SMALL_INT_MAX >> rhs_val)
457 [ - + ]: 4683380 : || lhs_val < (MP_SMALL_INT_MIN >> rhs_val)) {
458 : : // left-shift will overflow, so use higher precision integer
459 : 844 : lhs = mp_obj_new_int_from_ll(lhs_val);
460 : 844 : goto generic_binary_op;
461 : : } else {
462 : : // use standard precision
463 : 4683380 : lhs_val = (mp_uint_t)lhs_val << rhs_val;
464 : : }
465 : 4683380 : break;
466 : : }
467 : 10049 : case MP_BINARY_OP_RSHIFT:
468 : : case MP_BINARY_OP_INPLACE_RSHIFT:
469 [ + + ]: 10049 : if (rhs_val < 0) {
470 : : // negative shift not allowed
471 : 4 : mp_raise_ValueError(MP_ERROR_TEXT("negative shift count"));
472 : : } else {
473 : : // standard precision is enough for right-shift
474 [ + + ]: 10045 : if (rhs_val >= (mp_int_t)(sizeof(lhs_val) * MP_BITS_PER_BYTE)) {
475 : : // Shifting to big amounts is undefined behavior
476 : : // in C and is CPU-dependent; propagate sign bit.
477 : 12 : rhs_val = sizeof(lhs_val) * MP_BITS_PER_BYTE - 1;
478 : : }
479 : 10045 : lhs_val >>= rhs_val;
480 : : }
481 : 10045 : break;
482 : 17366355 : case MP_BINARY_OP_ADD:
483 : : case MP_BINARY_OP_INPLACE_ADD:
484 : 17366355 : lhs_val += rhs_val;
485 : 17366355 : break;
486 : 94705 : case MP_BINARY_OP_SUBTRACT:
487 : : case MP_BINARY_OP_INPLACE_SUBTRACT:
488 : 94705 : lhs_val -= rhs_val;
489 : 94705 : break;
490 : 3438265 : case MP_BINARY_OP_MULTIPLY:
491 : : case MP_BINARY_OP_INPLACE_MULTIPLY: {
492 : :
493 : : // If long long type exists and is larger than mp_int_t, then
494 : : // we can use the following code to perform overflow-checked multiplication.
495 : : // Otherwise (eg in x64 case) we must use mp_small_int_mul_overflow.
496 : : #if 0
497 : : // compute result using long long precision
498 : : long long res = (long long)lhs_val * (long long)rhs_val;
499 : : if (res > MP_SMALL_INT_MAX || res < MP_SMALL_INT_MIN) {
500 : : // result overflowed SMALL_INT, so return higher precision integer
501 : : return mp_obj_new_int_from_ll(res);
502 : : } else {
503 : : // use standard precision
504 : : lhs_val = (mp_int_t)res;
505 : : }
506 : : #endif
507 : :
508 [ + + ]: 3438265 : if (mp_small_int_mul_overflow(lhs_val, rhs_val)) {
509 : : // use higher precision
510 : 147 : lhs = mp_obj_new_int_from_ll(lhs_val);
511 : 147 : goto generic_binary_op;
512 : : } else {
513 : : // use standard precision
514 : 3440436 : return MP_OBJ_NEW_SMALL_INT(lhs_val * rhs_val);
515 : : }
516 : : }
517 : 5180 : case MP_BINARY_OP_FLOOR_DIVIDE:
518 : : case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE:
519 [ + + ]: 5180 : if (rhs_val == 0) {
520 : 9 : goto zero_division;
521 : : }
522 : 5171 : lhs_val = mp_small_int_floor_divide(lhs_val, rhs_val);
523 : 5171 : break;
524 : :
525 : : #if MICROPY_PY_BUILTINS_FLOAT
526 : 250 : case MP_BINARY_OP_TRUE_DIVIDE:
527 : : case MP_BINARY_OP_INPLACE_TRUE_DIVIDE:
528 [ + + ]: 250 : if (rhs_val == 0) {
529 : 66 : goto zero_division;
530 : : }
531 : 184 : return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val);
532 : : #endif
533 : :
534 : 97384 : case MP_BINARY_OP_MODULO:
535 : : case MP_BINARY_OP_INPLACE_MODULO: {
536 [ + + ]: 97384 : if (rhs_val == 0) {
537 : 4 : goto zero_division;
538 : : }
539 : 97380 : lhs_val = mp_small_int_modulo(lhs_val, rhs_val);
540 : 97380 : break;
541 : : }
542 : :
543 : 1964 : case MP_BINARY_OP_POWER:
544 : : case MP_BINARY_OP_INPLACE_POWER:
545 [ + + ]: 1964 : if (rhs_val < 0) {
546 : : #if MICROPY_PY_BUILTINS_FLOAT
547 : 524 : return mp_obj_float_binary_op(op, (mp_float_t)lhs_val, rhs);
548 : : #else
549 : : mp_raise_ValueError(MP_ERROR_TEXT("negative power with no float support"));
550 : : #endif
551 : : } else {
552 : : mp_int_t ans = 1;
553 [ + + ]: 3912 : while (rhs_val > 0) {
554 [ + + ]: 3710 : if (rhs_val & 1) {
555 [ + + ]: 2026 : if (mp_small_int_mul_overflow(ans, lhs_val)) {
556 : 160 : goto power_overflow;
557 : : }
558 : 1866 : ans *= lhs_val;
559 : : }
560 [ + + ]: 1866 : if (rhs_val == 1) {
561 : : break;
562 : : }
563 : 2676 : rhs_val /= 2;
564 [ + + ]: 2676 : if (mp_small_int_mul_overflow(lhs_val, lhs_val)) {
565 : 204 : goto power_overflow;
566 : : }
567 : 2472 : lhs_val *= lhs_val;
568 : : }
569 : : lhs_val = ans;
570 : : }
571 : : break;
572 : :
573 : 364 : power_overflow:
574 : : // use higher precision
575 : 364 : lhs = mp_obj_new_int_from_ll(MP_OBJ_SMALL_INT_VALUE(lhs));
576 : 364 : goto generic_binary_op;
577 : :
578 : 178 : case MP_BINARY_OP_DIVMOD: {
579 [ + + ]: 178 : if (rhs_val == 0) {
580 : 4 : goto zero_division;
581 : : }
582 : : // to reduce stack usage we don't pass a temp array of the 2 items
583 : 174 : mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
584 : 174 : tuple->items[0] = MP_OBJ_NEW_SMALL_INT(mp_small_int_floor_divide(lhs_val, rhs_val));
585 : 174 : tuple->items[1] = MP_OBJ_NEW_SMALL_INT(mp_small_int_modulo(lhs_val, rhs_val));
586 : 174 : return MP_OBJ_FROM_PTR(tuple);
587 : : }
588 : :
589 : 29572363 : case MP_BINARY_OP_LESS:
590 [ + + ]: 34068625 : return mp_obj_new_bool(lhs_val < rhs_val);
591 : 1343883 : case MP_BINARY_OP_MORE:
592 [ + + ]: 2368969 : return mp_obj_new_bool(lhs_val > rhs_val);
593 : 1378 : case MP_BINARY_OP_LESS_EQUAL:
594 [ + + ]: 1626 : return mp_obj_new_bool(lhs_val <= rhs_val);
595 : 13684 : case MP_BINARY_OP_MORE_EQUAL:
596 [ + + ]: 15260 : return mp_obj_new_bool(lhs_val >= rhs_val);
597 : :
598 : 8 : default:
599 : 8 : goto unsupported_op;
600 : : }
601 : : // This is an inlined version of mp_obj_new_int, for speed
602 [ + + ]: 42225871 : if (MP_SMALL_INT_FITS(lhs_val)) {
603 : 42225863 : return MP_OBJ_NEW_SMALL_INT(lhs_val);
604 : : } else {
605 : 8 : return mp_obj_new_int_from_ll(lhs_val);
606 : : }
607 : : #if MICROPY_PY_BUILTINS_FLOAT
608 [ - + - + : 9938 : } else if (mp_obj_is_float(rhs)) {
- + - + +
+ + + ]
609 : 6260 : mp_obj_t res = mp_obj_float_binary_op(op, (mp_float_t)lhs_val, rhs);
610 [ + + ]: 6260 : if (res == MP_OBJ_NULL) {
611 : 4 : goto unsupported_op;
612 : : } else {
613 : : return res;
614 : : }
615 : : #endif
616 : : #if MICROPY_PY_BUILTINS_COMPLEX
617 [ - + - + : 3678 : } else if (mp_obj_is_type(rhs, &mp_type_complex)) {
- + - + +
+ + + ]
618 : 44 : mp_obj_t res = mp_obj_complex_binary_op(op, (mp_float_t)lhs_val, 0, rhs);
619 [ + + ]: 44 : if (res == MP_OBJ_NULL) {
620 : 4 : goto unsupported_op;
621 : : } else {
622 : : return res;
623 : : }
624 : : #endif
625 : : }
626 : : }
627 : :
628 : : // Convert MP_BINARY_OP_IN to MP_BINARY_OP_CONTAINS with swapped args.
629 [ + + ]: 737203 : if (op == MP_BINARY_OP_IN) {
630 : 23776 : op = MP_BINARY_OP_CONTAINS;
631 : 23776 : mp_obj_t temp = lhs;
632 : 23776 : lhs = rhs;
633 : 23776 : rhs = temp;
634 : : }
635 : :
636 : : // generic binary_op supplied by type
637 : 738741 : const mp_obj_type_t *type;
638 : 713427 : generic_binary_op:
639 : 738741 : type = mp_obj_get_type(lhs);
640 [ + + ]: 738741 : if (MP_OBJ_TYPE_HAS_SLOT(type, binary_op)) {
641 : 738721 : mp_obj_t result = MP_OBJ_TYPE_GET_SLOT(type, binary_op)(op, lhs, rhs);
642 [ + + ]: 738542 : if (result != MP_OBJ_NULL) {
643 : : return result;
644 : : }
645 : : }
646 : :
647 : : // If this was an inplace method, fallback to the corresponding normal method.
648 : : // https://docs.python.org/3/reference/datamodel.html#object.__iadd__ :
649 : : // "If a specific method is not defined, the augmented assignment falls back
650 : : // to the normal methods."
651 [ + + ]: 839 : if (op >= MP_BINARY_OP_INPLACE_OR && op <= MP_BINARY_OP_INPLACE_POWER) {
652 : 44 : op += MP_BINARY_OP_OR - MP_BINARY_OP_INPLACE_OR;
653 : 44 : goto generic_binary_op;
654 : : }
655 : :
656 : : #if MICROPY_PY_REVERSE_SPECIAL_METHODS
657 [ + + ]: 795 : if (op >= MP_BINARY_OP_OR && op <= MP_BINARY_OP_POWER) {
658 : 139 : mp_obj_t t = rhs;
659 : 139 : rhs = lhs;
660 : 139 : lhs = t;
661 : 139 : op += MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR;
662 : 139 : goto generic_binary_op;
663 [ + + ]: 656 : } else if (op >= MP_BINARY_OP_REVERSE_OR) {
664 : : // Convert __rop__ back to __op__ for error message
665 : 94 : mp_obj_t t = rhs;
666 : 94 : rhs = lhs;
667 : 94 : lhs = t;
668 : 94 : op -= MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR;
669 : : }
670 : : #endif
671 : :
672 [ + + ]: 656 : if (op == MP_BINARY_OP_CONTAINS) {
673 : : // If type didn't support containment then explicitly walk the iterator.
674 : : // mp_getiter will raise the appropriate exception if lhs is not iterable.
675 : 520 : mp_obj_iter_buf_t iter_buf;
676 : 520 : mp_obj_t iter = mp_getiter(lhs, &iter_buf);
677 : 520 : mp_obj_t next;
678 [ + + ]: 2663 : while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
679 [ + + ]: 2548 : if (mp_obj_equal(next, rhs)) {
680 : : return mp_const_true;
681 : : }
682 : : }
683 : : return mp_const_false;
684 : : }
685 : :
686 : 136 : unsupported_op:
687 : : #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
688 : : mp_raise_TypeError(MP_ERROR_TEXT("unsupported type for operator"));
689 : : #else
690 : 160 : mp_raise_msg_varg(&mp_type_TypeError,
691 : 160 : MP_ERROR_TEXT("unsupported types for %q: '%s', '%s'"),
692 : 160 : mp_binary_op_method_name[op], mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs));
693 : : #endif
694 : :
695 : 83 : zero_division:
696 : 83 : mp_raise_msg(&mp_type_ZeroDivisionError, MP_ERROR_TEXT("divide by zero"));
697 : : }
698 : :
699 : 6736 : mp_obj_t mp_call_function_0(mp_obj_t fun) {
700 : 6736 : return mp_call_function_n_kw(fun, 0, 0, NULL);
701 : : }
702 : :
703 : 40241 : mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg) {
704 : 40241 : return mp_call_function_n_kw(fun, 1, 0, &arg);
705 : : }
706 : :
707 : 3452 : mp_obj_t mp_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) {
708 : 3452 : mp_obj_t args[2];
709 : 3452 : args[0] = arg1;
710 : 3452 : args[1] = arg2;
711 : 3452 : return mp_call_function_n_kw(fun, 2, 0, args);
712 : : }
713 : :
714 : : // args contains, eg: arg0 arg1 key0 value0 key1 value1
715 : 27318445 : mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
716 : : // TODO improve this: fun object can specify its type and we parse here the arguments,
717 : : // passing to the function arrays of fixed and keyword arguments
718 : :
719 : 27318445 : DEBUG_OP_printf("calling function %p(n_args=" UINT_FMT ", n_kw=" UINT_FMT ", args=%p)\n", fun_in, n_args, n_kw, args);
720 : :
721 : : // get the type
722 : 27318445 : const mp_obj_type_t *type = mp_obj_get_type(fun_in);
723 : :
724 : : // do the call
725 [ + + ]: 27586437 : if (MP_OBJ_TYPE_HAS_SLOT(type, call)) {
726 : 27586433 : return MP_OBJ_TYPE_GET_SLOT(type, call)(fun_in, n_args, n_kw, args);
727 : : }
728 : :
729 : : #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
730 : : mp_raise_TypeError(MP_ERROR_TEXT("object not callable"));
731 : : #else
732 : 4 : mp_raise_msg_varg(&mp_type_TypeError,
733 : 4 : MP_ERROR_TEXT("'%s' object isn't callable"), mp_obj_get_type_str(fun_in));
734 : : #endif
735 : : }
736 : :
737 : : // args contains: fun self/NULL arg(0) ... arg(n_args-2) arg(n_args-1) kw_key(0) kw_val(0) ... kw_key(n_kw-1) kw_val(n_kw-1)
738 : : // if n_args==0 and n_kw==0 then there are only fun and self/NULL
739 : 17419249 : mp_obj_t mp_call_method_n_kw(size_t n_args, size_t n_kw, const mp_obj_t *args) {
740 : 17419249 : DEBUG_OP_printf("call method (fun=%p, self=%p, n_args=" UINT_FMT ", n_kw=" UINT_FMT ", args=%p)\n", args[0], args[1], n_args, n_kw, args);
741 : 17419249 : int adjust = (args[1] == MP_OBJ_NULL) ? 0 : 1;
742 : 17419249 : return mp_call_function_n_kw(args[0], n_args + adjust, n_kw, args + 2 - adjust);
743 : : }
744 : :
745 : : // This function only needs to be exposed externally when in stackless mode.
746 : : #if !MICROPY_STACKLESS
747 : : static
748 : : #endif
749 : 9520 : void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args, mp_call_args_t *out_args) {
750 : 9520 : mp_obj_t fun = *args++;
751 : 9520 : mp_obj_t self = MP_OBJ_NULL;
752 [ + + ]: 9520 : if (have_self) {
753 : 4210 : self = *args++; // may be MP_OBJ_NULL
754 : : }
755 : 9520 : size_t n_args = n_args_n_kw & 0xff;
756 : 9520 : size_t n_kw = (n_args_n_kw >> 8) & 0xff;
757 : 9520 : mp_uint_t star_args = MP_OBJ_SMALL_INT_VALUE(args[n_args + 2 * n_kw]);
758 : :
759 : 9520 : DEBUG_OP_printf("call method var (fun=%p, self=%p, n_args=%u, n_kw=%u, args=%p, map=%u)\n", fun, self, n_args, n_kw, args, star_args);
760 : :
761 : : // We need to create the following array of objects:
762 : : // args[0 .. n_args] unpacked(pos_seq) args[n_args .. n_args + 2 * n_kw] unpacked(kw_dict)
763 : : // TODO: optimize one day to avoid constructing new arg array? Will be hard.
764 : :
765 : : // The new args array
766 : 9520 : mp_obj_t *args2;
767 : 9520 : size_t args2_alloc;
768 : 9520 : size_t args2_len = 0;
769 : :
770 : : // Try to get a hint for unpacked * args length
771 : 9520 : ssize_t list_len = 0;
772 : :
773 [ + + ]: 9520 : if (star_args != 0) {
774 [ + + ]: 22204 : for (size_t i = 0; i < n_args; i++) {
775 [ + + ]: 12946 : if ((star_args >> i) & 1) {
776 : 9286 : mp_obj_t len = mp_obj_len_maybe(args[i]);
777 [ + + ]: 9286 : if (len != MP_OBJ_NULL) {
778 : : // -1 accounts for 1 of n_args occupied by this arg
779 : 9190 : list_len += mp_obj_get_int(len) - 1;
780 : : }
781 : : }
782 : : }
783 : : }
784 : :
785 : : // Try to get a hint for the size of the kw_dict
786 : 9520 : ssize_t kw_dict_len = 0;
787 : :
788 [ + + ]: 9960 : for (size_t i = 0; i < n_kw; i++) {
789 : 440 : mp_obj_t key = args[n_args + i * 2];
790 : 440 : mp_obj_t value = args[n_args + i * 2 + 1];
791 [ + + - + : 440 : if (key == MP_OBJ_NULL && value != MP_OBJ_NULL && mp_obj_is_type(value, &mp_type_dict)) {
- + - + -
+ + - +
+ ]
792 : : // -1 accounts for 1 of n_kw occupied by this arg
793 : 372 : kw_dict_len += mp_obj_dict_len(value) - 1;
794 : : }
795 : : }
796 : :
797 : : // Extract the pos_seq sequence to the new args array.
798 : : // Note that it can be arbitrary iterator.
799 [ + + ]: 9520 : if (star_args == 0) {
800 : : // no star args to unpack
801 : :
802 : : // allocate memory for the new array of args
803 : 262 : args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len);
804 : 262 : args2 = mp_nonlocal_alloc(args2_alloc * sizeof(mp_obj_t));
805 : :
806 : : // copy the self
807 [ + + ]: 262 : if (self != MP_OBJ_NULL) {
808 : 34 : args2[args2_len++] = self;
809 : : }
810 : :
811 : : // copy the fixed pos args
812 : 262 : mp_seq_copy(args2 + args2_len, args, n_args, mp_obj_t);
813 : 262 : args2_len += n_args;
814 : : } else {
815 : : // at least one star arg to unpack
816 : :
817 : : // allocate memory for the new array of args
818 : 9258 : args2_alloc = 1 + n_args + list_len + 2 * (n_kw + kw_dict_len);
819 : 9258 : args2 = mp_nonlocal_alloc(args2_alloc * sizeof(mp_obj_t));
820 : :
821 : : // copy the self
822 [ + + ]: 9258 : if (self != MP_OBJ_NULL) {
823 : 3768 : args2[args2_len++] = self;
824 : : }
825 : :
826 [ + + ]: 22204 : for (size_t i = 0; i < n_args; i++) {
827 : 12946 : mp_obj_t arg = args[i];
828 [ + + ]: 12946 : if ((star_args >> i) & 1) {
829 : : // star arg
830 [ - + - + : 9286 : if (mp_obj_is_type(arg, &mp_type_tuple) || mp_obj_is_type(arg, &mp_type_list)) {
- + - + +
- + + - +
- + - + -
+ + - +
+ ]
831 : : // optimise the case of a tuple and list
832 : :
833 : : // get the items
834 : 9174 : size_t len;
835 : 9174 : mp_obj_t *items;
836 : 9174 : mp_obj_get_array(arg, &len, &items);
837 : :
838 : : // copy the items
839 [ - + ]: 9174 : assert(args2_len + len <= args2_alloc);
840 : 9174 : mp_seq_copy(args2 + args2_len, items, len, mp_obj_t);
841 : 9174 : args2_len += len;
842 : : } else {
843 : : // generic iterator
844 : :
845 : : // extract the variable position args from the iterator
846 : 112 : mp_obj_iter_buf_t iter_buf;
847 : 112 : mp_obj_t iterable = mp_getiter(arg, &iter_buf);
848 : 112 : mp_obj_t item;
849 [ + + ]: 928 : while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
850 [ + + ]: 816 : if (args2_len + (n_args - i) >= args2_alloc) {
851 : 92 : args2 = mp_nonlocal_realloc(args2, args2_alloc * sizeof(mp_obj_t),
852 : : args2_alloc * 2 * sizeof(mp_obj_t));
853 : 92 : args2_alloc *= 2;
854 : : }
855 : 816 : args2[args2_len++] = item;
856 : : }
857 : : }
858 : : } else {
859 : : // normal argument
860 [ - + ]: 3660 : assert(args2_len < args2_alloc);
861 : 3660 : args2[args2_len++] = arg;
862 : : }
863 : : }
864 : : }
865 : :
866 : : // The size of the args2 array now is the number of positional args.
867 : 9520 : size_t pos_args_len = args2_len;
868 : :
869 : : // ensure there is still enough room for kw args
870 [ + + ]: 9520 : if (args2_len + 2 * (n_kw + kw_dict_len) > args2_alloc) {
871 : 4 : size_t new_alloc = args2_len + 2 * (n_kw + kw_dict_len);
872 : 4 : args2 = mp_nonlocal_realloc(args2, args2_alloc * sizeof(mp_obj_t),
873 : : new_alloc * sizeof(mp_obj_t));
874 : 4 : args2_alloc = new_alloc;
875 : : }
876 : :
877 : : // Copy the kw args.
878 [ + + ]: 9950 : for (size_t i = 0; i < n_kw; i++) {
879 : 440 : mp_obj_t kw_key = args[n_args + i * 2];
880 : 440 : mp_obj_t kw_value = args[n_args + i * 2 + 1];
881 [ + + ]: 440 : if (kw_key == MP_OBJ_NULL) {
882 : : // double-star args
883 [ - + - + : 376 : if (mp_obj_is_type(kw_value, &mp_type_dict)) {
- + - + +
- + + ]
884 : : // dictionary
885 [ - + ]: 372 : mp_map_t *map = mp_obj_dict_get_map(kw_value);
886 : : // should have enough, since kw_dict_len is in this case hinted correctly above
887 [ - + ]: 372 : assert(args2_len + 2 * map->used <= args2_alloc);
888 [ + + ]: 1164 : for (size_t j = 0; j < map->alloc; j++) {
889 [ + + ]: 802 : if (mp_map_slot_is_filled(map, j)) {
890 : : // the key must be a qstr, so intern it if it's a string
891 : 686 : mp_obj_t key = map->table[j].key;
892 [ + + ]: 686 : if (!mp_obj_is_qstr(key)) {
893 : 414 : key = mp_obj_str_intern_checked(key);
894 : : }
895 : 676 : args2[args2_len++] = key;
896 : 676 : args2[args2_len++] = map->table[j].value;
897 : : }
898 : : }
899 : : } else {
900 : : // generic mapping:
901 : : // - call keys() to get an iterable of all keys in the mapping
902 : : // - call __getitem__ for each key to get the corresponding value
903 : :
904 : : // get the keys iterable
905 : 4 : mp_obj_t dest[3];
906 : 4 : mp_load_method(kw_value, MP_QSTR_keys, dest);
907 : 4 : mp_obj_t iterable = mp_getiter(mp_call_method_n_kw(0, 0, dest), NULL);
908 : :
909 : 4 : mp_obj_t key;
910 [ + + ]: 20 : while ((key = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
911 : : // expand size of args array if needed
912 [ + + ]: 16 : if (args2_len + 1 >= args2_alloc) {
913 : 8 : size_t new_alloc = args2_alloc * 2;
914 : 8 : args2 = mp_nonlocal_realloc(args2, args2_alloc * sizeof(mp_obj_t), new_alloc * sizeof(mp_obj_t));
915 : 8 : args2_alloc = new_alloc;
916 : : }
917 : :
918 : : // the key must be a qstr, so intern it if it's a string
919 [ + + ]: 16 : if (!mp_obj_is_qstr(key)) {
920 : 4 : key = mp_obj_str_intern_checked(key);
921 : : }
922 : :
923 : : // get the value corresponding to the key
924 : 16 : mp_load_method(kw_value, MP_QSTR___getitem__, dest);
925 : 16 : dest[2] = key;
926 : 16 : mp_obj_t value = mp_call_method_n_kw(1, 0, dest);
927 : :
928 : : // store the key/value pair in the argument array
929 : 16 : args2[args2_len++] = key;
930 : 16 : args2[args2_len++] = value;
931 : : }
932 : : }
933 : : } else {
934 : : // normal kwarg
935 [ - + ]: 64 : assert(args2_len + 2 <= args2_alloc);
936 : 64 : args2[args2_len++] = kw_key;
937 : 64 : args2[args2_len++] = kw_value;
938 : : }
939 : : }
940 : :
941 : 9510 : out_args->fun = fun;
942 : 9510 : out_args->args = args2;
943 : 9510 : out_args->n_args = pos_args_len;
944 : 9510 : out_args->n_kw = (args2_len - pos_args_len) / 2;
945 : 9510 : out_args->n_alloc = args2_alloc;
946 : 9510 : }
947 : :
948 : 9520 : mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args) {
949 : 9520 : mp_call_args_t out_args;
950 : 9520 : mp_call_prepare_args_n_kw_var(have_self, n_args_n_kw, args, &out_args);
951 : :
952 : 9510 : mp_obj_t res = mp_call_function_n_kw(out_args.fun, out_args.n_args, out_args.n_kw, out_args.args);
953 : 9166 : mp_nonlocal_free(out_args.args, out_args.n_alloc * sizeof(mp_obj_t));
954 : :
955 : 9166 : return res;
956 : : }
957 : :
958 : : // unpacked items are stored in reverse order into the array pointed to by items
959 : 40135 : void mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) {
960 : 40135 : size_t seq_len;
961 [ - + - + : 80210 : if (mp_obj_is_type(seq_in, &mp_type_tuple) || mp_obj_is_type(seq_in, &mp_type_list)) {
- + - + +
- + + - +
- + - + -
+ + - +
+ ]
962 : 40083 : mp_obj_t *seq_items;
963 : 40083 : mp_obj_get_array(seq_in, &seq_len, &seq_items);
964 [ + + ]: 40083 : if (seq_len < num) {
965 : 4 : goto too_short;
966 [ + + ]: 40079 : } else if (seq_len > num) {
967 : 4 : goto too_long;
968 : : }
969 [ + + ]: 120477 : for (size_t i = 0; i < num; i++) {
970 : 80402 : items[i] = seq_items[num - 1 - i];
971 : : }
972 : : } else {
973 : 52 : mp_obj_iter_buf_t iter_buf;
974 : 52 : mp_obj_t iterable = mp_getiter(seq_in, &iter_buf);
975 : :
976 [ + + ]: 164 : for (seq_len = 0; seq_len < num; seq_len++) {
977 : 116 : mp_obj_t el = mp_iternext(iterable);
978 [ + + ]: 116 : if (el == MP_OBJ_STOP_ITERATION) {
979 : 4 : goto too_short;
980 : : }
981 : 112 : items[num - 1 - seq_len] = el;
982 : : }
983 [ + + ]: 48 : if (mp_iternext(iterable) != MP_OBJ_STOP_ITERATION) {
984 : 4 : goto too_long;
985 : : }
986 : : }
987 : 40119 : return;
988 : :
989 : 8 : too_short:
990 : : #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
991 : : mp_raise_ValueError(MP_ERROR_TEXT("wrong number of values to unpack"));
992 : : #else
993 : 8 : mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("need more than %d values to unpack"), (int)seq_len);
994 : : #endif
995 : 8 : too_long:
996 : : #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
997 : : mp_raise_ValueError(MP_ERROR_TEXT("wrong number of values to unpack"));
998 : : #else
999 : 8 : mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("too many values to unpack (expected %d)"), (int)num);
1000 : : #endif
1001 : : }
1002 : :
1003 : : // unpacked items are stored in reverse order into the array pointed to by items
1004 : 180 : void mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) {
1005 : 180 : size_t num_left = num_in & 0xff;
1006 : 180 : size_t num_right = (num_in >> 8) & 0xff;
1007 : 180 : DEBUG_OP_printf("unpack ex " UINT_FMT " " UINT_FMT "\n", num_left, num_right);
1008 : 180 : size_t seq_len;
1009 [ - + - + : 180 : if (mp_obj_is_type(seq_in, &mp_type_tuple) || mp_obj_is_type(seq_in, &mp_type_list)) {
- + - + +
- + + - +
- + - + -
+ + - +
+ ]
1010 : : // Make the seq variable volatile so the compiler keeps a reference to it,
1011 : : // since if it's a tuple then seq_items points to the interior of the GC cell
1012 : : // and mp_obj_new_list may trigger a GC which doesn't trace this and reclaims seq.
1013 : 136 : volatile mp_obj_t seq = seq_in;
1014 : 136 : mp_obj_t *seq_items;
1015 : 136 : mp_obj_get_array(seq, &seq_len, &seq_items);
1016 [ + + ]: 136 : if (seq_len < num_left + num_right) {
1017 : 4 : goto too_short;
1018 : : }
1019 [ + + ]: 164 : for (size_t i = 0; i < num_right; i++) {
1020 : 32 : items[i] = seq_items[seq_len - 1 - i];
1021 : : }
1022 : 132 : items[num_right] = mp_obj_new_list(seq_len - num_left - num_right, seq_items + num_left);
1023 [ + + ]: 224 : for (size_t i = 0; i < num_left; i++) {
1024 : 92 : items[num_right + 1 + i] = seq_items[num_left - 1 - i];
1025 : : }
1026 : 132 : seq = MP_OBJ_NULL;
1027 : : } else {
1028 : : // Generic iterable; this gets a bit messy: we unpack known left length to the
1029 : : // items destination array, then the rest to a dynamically created list. Once the
1030 : : // iterable is exhausted, we take from this list for the right part of the items.
1031 : : // TODO Improve to waste less memory in the dynamically created list.
1032 : 44 : mp_obj_t iterable = mp_getiter(seq_in, NULL);
1033 : 44 : mp_obj_t item;
1034 [ + + ]: 84 : for (seq_len = 0; seq_len < num_left; seq_len++) {
1035 : 44 : item = mp_iternext(iterable);
1036 [ + + ]: 44 : if (item == MP_OBJ_STOP_ITERATION) {
1037 : 4 : goto too_short;
1038 : : }
1039 : 40 : items[num_left + num_right + 1 - 1 - seq_len] = item;
1040 : : }
1041 : 40 : mp_obj_list_t *rest = MP_OBJ_TO_PTR(mp_obj_new_list(0, NULL));
1042 [ + + ]: 184 : while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
1043 : 144 : mp_obj_list_append(MP_OBJ_FROM_PTR(rest), item);
1044 : : }
1045 [ + + ]: 40 : if (rest->len < num_right) {
1046 : 4 : goto too_short;
1047 : : }
1048 : 36 : items[num_right] = MP_OBJ_FROM_PTR(rest);
1049 [ + + ]: 72 : for (size_t i = 0; i < num_right; i++) {
1050 : 36 : items[num_right - 1 - i] = rest->items[rest->len - num_right + i];
1051 : : }
1052 : 36 : mp_obj_list_set_len(MP_OBJ_FROM_PTR(rest), rest->len - num_right);
1053 : : }
1054 : 168 : return;
1055 : :
1056 : 12 : too_short:
1057 : : #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
1058 : : mp_raise_ValueError(MP_ERROR_TEXT("wrong number of values to unpack"));
1059 : : #else
1060 : 12 : mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("need more than %d values to unpack"), (int)seq_len);
1061 : : #endif
1062 : : }
1063 : :
1064 : 3369088 : mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
1065 : 3369088 : DEBUG_OP_printf("load attr %p.%s\n", base, qstr_str(attr));
1066 : : // use load_method
1067 : 3369088 : mp_obj_t dest[2];
1068 : 3369088 : mp_load_method(base, attr, dest);
1069 [ + + ]: 3369006 : if (dest[1] == MP_OBJ_NULL) {
1070 : : // load_method returned just a normal attribute
1071 : 3368803 : return dest[0];
1072 : : } else {
1073 : : // load_method returned a method, so build a bound method object
1074 : 203 : return mp_obj_new_bound_meth(dest[0], dest[1]);
1075 : : }
1076 : : }
1077 : :
1078 : : #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG
1079 : :
1080 : : // The following "checked fun" type is local to the mp_convert_member_lookup
1081 : : // function, and serves to check that the first argument to a builtin function
1082 : : // has the correct type.
1083 : :
1084 : : typedef struct _mp_obj_checked_fun_t {
1085 : : mp_obj_base_t base;
1086 : : const mp_obj_type_t *type;
1087 : : mp_obj_t fun;
1088 : : } mp_obj_checked_fun_t;
1089 : :
1090 : 26 : static mp_obj_t checked_fun_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
1091 : 26 : mp_obj_checked_fun_t *self = MP_OBJ_TO_PTR(self_in);
1092 [ + + ]: 26 : if (n_args > 0) {
1093 : 22 : const mp_obj_type_t *arg0_type = mp_obj_get_type(args[0]);
1094 [ + + ]: 22 : if (arg0_type != self->type) {
1095 : : #if MICROPY_ERROR_REPORTING != MICROPY_ERROR_REPORTING_DETAILED
1096 : : mp_raise_TypeError(MP_ERROR_TEXT("argument has wrong type"));
1097 : : #else
1098 : 12 : mp_raise_msg_varg(&mp_type_TypeError,
1099 : 12 : MP_ERROR_TEXT("argument should be a '%q' not a '%q'"), self->type->name, arg0_type->name);
1100 : : #endif
1101 : : }
1102 : : }
1103 : 14 : return mp_call_function_n_kw(self->fun, n_args, n_kw, args);
1104 : : }
1105 : :
1106 : : static MP_DEFINE_CONST_OBJ_TYPE(
1107 : : mp_type_checked_fun,
1108 : : MP_QSTR_function,
1109 : : MP_TYPE_FLAG_BINDS_SELF,
1110 : : call, checked_fun_call
1111 : : );
1112 : :
1113 : 133 : static mp_obj_t mp_obj_new_checked_fun(const mp_obj_type_t *type, mp_obj_t fun) {
1114 : 133 : mp_obj_checked_fun_t *o = mp_obj_malloc(mp_obj_checked_fun_t, &mp_type_checked_fun);
1115 : 133 : o->type = type;
1116 : 133 : o->fun = fun;
1117 : 133 : return MP_OBJ_FROM_PTR(o);
1118 : : }
1119 : :
1120 : : #endif // MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG
1121 : :
1122 : : // Given a member that was extracted from an instance, convert it correctly
1123 : : // and put the result in the dest[] array for a possible method call.
1124 : : // Conversion means dealing with static/class methods, callables, and values.
1125 : : // see http://docs.python.org/3/howto/descriptor.html
1126 : : // and also https://mail.python.org/pipermail/python-dev/2015-March/138950.html
1127 : 3505354 : void mp_convert_member_lookup(mp_obj_t self, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest) {
1128 [ + + ]: 3505354 : if (mp_obj_is_obj(member)) {
1129 : 3047075 : const mp_obj_type_t *m_type = ((mp_obj_base_t *)MP_OBJ_TO_PTR(member))->type;
1130 [ + + ]: 3047075 : if (m_type->flags & MP_TYPE_FLAG_BINDS_SELF) {
1131 : : // `member` is a function that binds self as its first argument.
1132 [ + + ]: 3046323 : if (m_type->flags & MP_TYPE_FLAG_BUILTIN_FUN) {
1133 : : // `member` is a built-in function, which has special behaviour.
1134 [ + + ]: 1870662 : if (mp_obj_is_instance_type(type)) {
1135 : : // Built-in functions on user types always behave like a staticmethod.
1136 : 8 : dest[0] = member;
1137 : : }
1138 : : #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG
1139 [ + + + + ]: 1870654 : else if (self == MP_OBJ_NULL && type != &mp_type_object) {
1140 : : // `member` is a built-in method without a first argument, so wrap
1141 : : // it in a type checker that will check self when it's supplied.
1142 : : // Note that object will do its own checking so shouldn't be wrapped.
1143 : 133 : dest[0] = mp_obj_new_checked_fun(type, member);
1144 : : }
1145 : : #endif
1146 : : else {
1147 : : // Return a (built-in) bound method, with self being this object.
1148 : 1870521 : dest[0] = member;
1149 : 1870521 : dest[1] = self;
1150 : : }
1151 : : } else {
1152 : : // Return a bound method, with self being this object.
1153 : 1175661 : dest[0] = member;
1154 : 1175661 : dest[1] = self;
1155 : : }
1156 [ + + ]: 752 : } else if (m_type == &mp_type_staticmethod) {
1157 : : // `member` is a staticmethod, return the function that it wraps.
1158 : 162 : dest[0] = ((mp_obj_static_class_method_t *)MP_OBJ_TO_PTR(member))->fun;
1159 [ + + ]: 590 : } else if (m_type == &mp_type_classmethod) {
1160 : : // `member` is a classmethod, return a bound method with self being the type of
1161 : : // this object. This type should be the type of the original instance, not the
1162 : : // base type (which is what is passed in the `type` argument to this function).
1163 [ + + ]: 222 : if (self != MP_OBJ_NULL) {
1164 : 48 : type = mp_obj_get_type(self);
1165 [ + + ]: 48 : if (type == &mp_type_type) {
1166 : : // `self` is already a type, so use `self` directly.
1167 : 16 : type = MP_OBJ_TO_PTR(self);
1168 : : }
1169 : : }
1170 : 222 : dest[0] = ((mp_obj_static_class_method_t *)MP_OBJ_TO_PTR(member))->fun;
1171 : 222 : dest[1] = MP_OBJ_FROM_PTR(type);
1172 : : } else {
1173 : : // `member` is a value, so just return that value.
1174 : 368 : dest[0] = member;
1175 : : }
1176 : : } else {
1177 : : // `member` is a value, so just return that value.
1178 : 458279 : dest[0] = member;
1179 : : }
1180 : 3505354 : }
1181 : :
1182 : : // no attribute found, returns: dest[0] == MP_OBJ_NULL, dest[1] == MP_OBJ_NULL
1183 : : // normal attribute found, returns: dest[0] == <attribute>, dest[1] == MP_OBJ_NULL
1184 : : // method attribute found, returns: dest[0] == <method>, dest[1] == <self>
1185 : 20606480 : void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) {
1186 : : // clear output to indicate no attribute/method found yet
1187 : 20606480 : dest[0] = MP_OBJ_NULL;
1188 : 20606480 : dest[1] = MP_OBJ_NULL;
1189 : :
1190 : : // Note: the specific case of obj being an instance type is fast-path'ed in the VM
1191 : : // for the MP_BC_LOAD_ATTR opcode. Instance types handle type->attr and look up directly
1192 : : // in their member's map.
1193 : :
1194 : : // get the type
1195 : 20606480 : const mp_obj_type_t *type = mp_obj_get_type(obj);
1196 : :
1197 : : // look for built-in names
1198 : : #if MICROPY_CPYTHON_COMPAT
1199 [ + + ]: 20606281 : if (attr == MP_QSTR___class__) {
1200 : : // a.__class__ is equivalent to type(a)
1201 : 84 : dest[0] = MP_OBJ_FROM_PTR(type);
1202 : 84 : return;
1203 : : }
1204 : : #endif
1205 : :
1206 [ + + + + ]: 20606197 : if (attr == MP_QSTR___next__ && TYPE_HAS_ITERNEXT(type)) {
1207 : 4 : dest[0] = MP_OBJ_FROM_PTR(&mp_builtin_next_obj);
1208 : 4 : dest[1] = obj;
1209 : 4 : return;
1210 : : }
1211 [ + + ]: 20606193 : if (MP_OBJ_TYPE_HAS_SLOT(type, attr)) {
1212 : : // this type can do its own load, so call it
1213 : 18724498 : MP_OBJ_TYPE_GET_SLOT(type, attr)(obj, attr, dest);
1214 : : // If type->attr has set dest[1] = MP_OBJ_SENTINEL, we should proceed
1215 : : // with lookups below (i.e. in locals_dict). If not, return right away.
1216 [ + + ]: 18724598 : if (dest[1] != MP_OBJ_SENTINEL) {
1217 : : return;
1218 : : }
1219 : : // Clear the fail flag set by type->attr so it's like it never ran.
1220 : 1172 : dest[1] = MP_OBJ_NULL;
1221 : : }
1222 [ + + ]: 1882867 : if (MP_OBJ_TYPE_HAS_SLOT(type, locals_dict)) {
1223 : : // generic method lookup
1224 : : // this is a lookup in the object (ie not class or type)
1225 [ - + ]: 1881321 : assert(MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->base.type == &mp_type_dict); // MicroPython restriction, for now
1226 : 1881321 : mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->map;
1227 : 1881321 : mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
1228 [ + + ]: 1881315 : if (elem != NULL) {
1229 : 1870438 : mp_convert_member_lookup(obj, type, elem->value, dest);
1230 : : }
1231 : 1881314 : return;
1232 : : }
1233 : : }
1234 : :
1235 : 19905635 : void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) {
1236 : 19905635 : DEBUG_OP_printf("load method %p.%s\n", base, qstr_str(attr));
1237 : :
1238 : 19905635 : mp_load_method_maybe(base, attr, dest);
1239 : :
1240 [ + + ]: 19905490 : if (dest[0] == MP_OBJ_NULL) {
1241 : : // no attribute/method called attr
1242 : : #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
1243 : : mp_raise_msg(&mp_type_AttributeError, MP_ERROR_TEXT("no such attribute"));
1244 : : #else
1245 : : // following CPython, we give a more detailed error message for type objects
1246 [ - + - + : 92 : if (mp_obj_is_type(base, &mp_type_type)) {
- + - + +
+ + + ]
1247 : 8 : mp_raise_msg_varg(&mp_type_AttributeError,
1248 : 8 : MP_ERROR_TEXT("type object '%q' has no attribute '%q'"),
1249 : 8 : ((mp_obj_type_t *)MP_OBJ_TO_PTR(base))->name, attr);
1250 : : } else {
1251 : 84 : mp_raise_msg_varg(&mp_type_AttributeError,
1252 : 84 : MP_ERROR_TEXT("'%s' object has no attribute '%q'"),
1253 : : mp_obj_get_type_str(base), attr);
1254 : : }
1255 : : #endif
1256 : : }
1257 : 19905398 : }
1258 : :
1259 : : // Acts like mp_load_method_maybe but catches AttributeError, and all other exceptions if requested
1260 : 77808 : void mp_load_method_protected(mp_obj_t obj, qstr attr, mp_obj_t *dest, bool catch_all_exc) {
1261 : 77808 : nlr_buf_t nlr;
1262 [ + + ]: 77808 : if (nlr_push(&nlr) == 0) {
1263 : 77808 : mp_load_method_maybe(obj, attr, dest);
1264 : 77792 : nlr_pop();
1265 : : } else {
1266 [ + - ]: 16 : if (!catch_all_exc
1267 [ + + ]: 16 : && !mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type),
1268 : : MP_OBJ_FROM_PTR(&mp_type_AttributeError))) {
1269 : : // Re-raise the exception
1270 : 4 : nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val));
1271 : : }
1272 : : }
1273 : 77804 : }
1274 : :
1275 : 895529 : void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) {
1276 : 895529 : DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value);
1277 : 895529 : const mp_obj_type_t *type = mp_obj_get_type(base);
1278 [ + - ]: 895819 : if (MP_OBJ_TYPE_HAS_SLOT(type, attr)) {
1279 : 895819 : mp_obj_t dest[2] = {MP_OBJ_SENTINEL, value};
1280 : 895819 : MP_OBJ_TYPE_GET_SLOT(type, attr)(base, attr, dest);
1281 [ + + ]: 895808 : if (dest[0] == MP_OBJ_NULL) {
1282 : : // success
1283 : 895724 : return;
1284 : : }
1285 : : }
1286 : : #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
1287 : : mp_raise_msg(&mp_type_AttributeError, MP_ERROR_TEXT("no such attribute"));
1288 : : #else
1289 : 84 : mp_raise_msg_varg(&mp_type_AttributeError,
1290 : 84 : MP_ERROR_TEXT("'%s' object has no attribute '%q'"),
1291 : : mp_obj_get_type_str(base), attr);
1292 : : #endif
1293 : : }
1294 : :
1295 : 629967 : mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {
1296 [ - + ]: 629967 : assert(o_in);
1297 : 629967 : const mp_obj_type_t *type = mp_obj_get_type(o_in);
1298 : :
1299 : : // Most types that use iternext just use the identity getiter. We handle this case explicitly
1300 : : // so we don't unnecessarily allocate any RAM for the iter_buf, which won't be used.
1301 [ + + + - ]: 629967 : if ((type->flags & MP_TYPE_FLAG_ITER_IS_ITERNEXT) == MP_TYPE_FLAG_ITER_IS_ITERNEXT || (type->flags & MP_TYPE_FLAG_ITER_IS_STREAM) == MP_TYPE_FLAG_ITER_IS_STREAM) {
1302 : : return o_in;
1303 : : }
1304 : :
1305 [ + + ]: 325796 : if (MP_OBJ_TYPE_HAS_SLOT(type, iter)) {
1306 : : // check for native getiter (corresponds to __iter__)
1307 [ + + + + ]: 325776 : if (iter_buf == NULL && MP_OBJ_TYPE_GET_SLOT(type, iter) != mp_obj_instance_getiter) {
1308 : : // if caller did not provide a buffer then allocate one on the heap
1309 : : // mp_obj_instance_getiter is special, it will allocate only if needed
1310 : 32265 : iter_buf = m_new_obj(mp_obj_iter_buf_t);
1311 : : }
1312 : 325776 : mp_getiter_fun_t getiter;
1313 [ + + ]: 325776 : if (type->flags & MP_TYPE_FLAG_ITER_IS_CUSTOM) {
1314 : 158 : getiter = ((mp_getiter_iternext_custom_t *)MP_OBJ_TYPE_GET_SLOT(type, iter))->getiter;
1315 : : } else {
1316 : 325618 : getiter = (mp_getiter_fun_t)MP_OBJ_TYPE_GET_SLOT(type, iter);
1317 : : }
1318 : 325776 : mp_obj_t iter = getiter(o_in, iter_buf);
1319 [ + + ]: 325774 : if (iter != MP_OBJ_NULL) {
1320 : : return iter;
1321 : : }
1322 : : }
1323 : :
1324 : : // check for __getitem__
1325 : 48 : mp_obj_t dest[2];
1326 : 48 : mp_load_method_maybe(o_in, MP_QSTR___getitem__, dest);
1327 [ + + ]: 48 : if (dest[0] != MP_OBJ_NULL) {
1328 : : // __getitem__ exists, create and return an iterator
1329 [ + + ]: 20 : if (iter_buf == NULL) {
1330 : : // if caller did not provide a buffer then allocate one on the heap
1331 : 12 : iter_buf = m_new_obj(mp_obj_iter_buf_t);
1332 : : }
1333 : 20 : return mp_obj_new_getitem_iter(dest, iter_buf);
1334 : : }
1335 : :
1336 : : // object not iterable
1337 : : #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
1338 : : mp_raise_TypeError(MP_ERROR_TEXT("object not iterable"));
1339 : : #else
1340 : 28 : mp_raise_msg_varg(&mp_type_TypeError,
1341 : 28 : MP_ERROR_TEXT("'%s' object isn't iterable"), mp_obj_get_type_str(o_in));
1342 : : #endif
1343 : :
1344 : : }
1345 : :
1346 : 720765 : static mp_fun_1_t type_get_iternext(const mp_obj_type_t *type) {
1347 [ + + ]: 720765 : if ((type->flags & MP_TYPE_FLAG_ITER_IS_STREAM) == MP_TYPE_FLAG_ITER_IS_STREAM) {
1348 : : return mp_stream_unbuffered_iter;
1349 [ + + ]: 720717 : } else if (type->flags & MP_TYPE_FLAG_ITER_IS_ITERNEXT) {
1350 : 720409 : return (mp_fun_1_t)MP_OBJ_TYPE_GET_SLOT(type, iter);
1351 [ + - ]: 308 : } else if (type->flags & MP_TYPE_FLAG_ITER_IS_CUSTOM) {
1352 : 308 : return ((mp_getiter_iternext_custom_t *)MP_OBJ_TYPE_GET_SLOT(type, iter))->iternext;
1353 : : } else {
1354 : : return NULL;
1355 : : }
1356 : : }
1357 : :
1358 : : // may return MP_OBJ_STOP_ITERATION as an optimisation instead of raise StopIteration()
1359 : : // may also raise StopIteration()
1360 : 188191 : mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) {
1361 : 188191 : const mp_obj_type_t *type = mp_obj_get_type(o_in);
1362 [ + + ]: 188174 : if (TYPE_HAS_ITERNEXT(type)) {
1363 : 188134 : MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL;
1364 : 188135 : return type_get_iternext(type)(o_in);
1365 : : } else {
1366 : : // check for __next__ method
1367 : 40 : mp_obj_t dest[2];
1368 : 40 : mp_load_method_maybe(o_in, MP_QSTR___next__, dest);
1369 [ + + ]: 40 : if (dest[0] != MP_OBJ_NULL) {
1370 : : // __next__ exists, call it and return its result
1371 : 36 : return mp_call_method_n_kw(0, 0, dest);
1372 : : } else {
1373 : : #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
1374 : : mp_raise_TypeError(MP_ERROR_TEXT("object not an iterator"));
1375 : : #else
1376 : 4 : mp_raise_msg_varg(&mp_type_TypeError,
1377 : 4 : MP_ERROR_TEXT("'%s' object isn't an iterator"), mp_obj_get_type_str(o_in));
1378 : : #endif
1379 : : }
1380 : : }
1381 : : }
1382 : :
1383 : : // will always return MP_OBJ_STOP_ITERATION instead of raising StopIteration() (or any subclass thereof)
1384 : : // may raise other exceptions
1385 : 532578 : mp_obj_t mp_iternext(mp_obj_t o_in) {
1386 : 532578 : mp_cstack_check(); // enumerate, filter, map and zip can recursively call mp_iternext
1387 : 532552 : const mp_obj_type_t *type = mp_obj_get_type(o_in);
1388 [ + + ]: 532549 : if (TYPE_HAS_ITERNEXT(type)) {
1389 : 532421 : MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL;
1390 : 532413 : return type_get_iternext(type)(o_in);
1391 : : } else {
1392 : : // check for __next__ method
1393 : 128 : mp_obj_t dest[2];
1394 : 128 : mp_load_method_maybe(o_in, MP_QSTR___next__, dest);
1395 [ + + ]: 128 : if (dest[0] != MP_OBJ_NULL) {
1396 : : // __next__ exists, call it and return its result
1397 : 124 : nlr_buf_t nlr;
1398 [ + + ]: 124 : if (nlr_push(&nlr) == 0) {
1399 : 124 : mp_obj_t ret = mp_call_method_n_kw(0, 0, dest);
1400 : 72 : nlr_pop();
1401 : 72 : return ret;
1402 : : } else {
1403 [ + + ]: 52 : if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
1404 : 46 : return mp_make_stop_iteration(mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)));
1405 : : } else {
1406 : 6 : nlr_jump(nlr.ret_val);
1407 : : }
1408 : : }
1409 : : } else {
1410 : : #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
1411 : : mp_raise_TypeError(MP_ERROR_TEXT("object not an iterator"));
1412 : : #else
1413 : 4 : mp_raise_msg_varg(&mp_type_TypeError,
1414 : 4 : MP_ERROR_TEXT("'%s' object isn't an iterator"), mp_obj_get_type_str(o_in));
1415 : : #endif
1416 : : }
1417 : : }
1418 : : }
1419 : :
1420 : 577388 : mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {
1421 [ - + ]: 577388 : assert((send_value != MP_OBJ_NULL) ^ (throw_value != MP_OBJ_NULL));
1422 : 577388 : const mp_obj_type_t *type = mp_obj_get_type(self_in);
1423 : :
1424 [ + + ]: 577388 : if (type == &mp_type_gen_instance) {
1425 : 1632 : return mp_obj_gen_resume(self_in, send_value, throw_value, ret_val);
1426 : : }
1427 : :
1428 [ + + + + ]: 575756 : if (TYPE_HAS_ITERNEXT(type) && send_value == mp_const_none) {
1429 : 322 : MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL;
1430 : 322 : mp_obj_t ret = type_get_iternext(type)(self_in);
1431 : 190 : *ret_val = ret;
1432 [ + + ]: 190 : if (ret != MP_OBJ_STOP_ITERATION) {
1433 : : return MP_VM_RETURN_YIELD;
1434 : : } else {
1435 : : // The generator is finished.
1436 : : // This is an optimised "raise StopIteration(*ret_val)".
1437 : 20 : *ret_val = MP_STATE_THREAD(stop_iteration_arg);
1438 [ + - ]: 20 : if (*ret_val == MP_OBJ_NULL) {
1439 : 20 : *ret_val = mp_const_none;
1440 : : }
1441 : 20 : return MP_VM_RETURN_NORMAL;
1442 : : }
1443 : : }
1444 : :
1445 : 575424 : mp_obj_t dest[3]; // Reserve slot for send() arg
1446 : :
1447 : : // Python instance iterator protocol
1448 [ + + ]: 575424 : if (send_value == mp_const_none) {
1449 : 575310 : mp_load_method_maybe(self_in, MP_QSTR___next__, dest);
1450 [ + - ]: 575310 : if (dest[0] != MP_OBJ_NULL) {
1451 : 575310 : *ret_val = mp_call_method_n_kw(0, 0, dest);
1452 : 287735 : return MP_VM_RETURN_YIELD;
1453 : : }
1454 : : }
1455 : :
1456 : : // Either python instance generator protocol, or native object
1457 : : // generator protocol.
1458 [ + + ]: 124 : if (send_value != MP_OBJ_NULL) {
1459 : 8 : mp_load_method(self_in, MP_QSTR_send, dest);
1460 : 8 : dest[2] = send_value;
1461 : 8 : *ret_val = mp_call_method_n_kw(1, 0, dest);
1462 : 8 : return MP_VM_RETURN_YIELD;
1463 : : }
1464 : :
1465 [ - + ]: 116 : assert(throw_value != MP_OBJ_NULL);
1466 : : {
1467 [ + + ]: 116 : if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(throw_value)), MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) {
1468 : 8 : mp_load_method_maybe(self_in, MP_QSTR_close, dest);
1469 [ + + ]: 8 : if (dest[0] != MP_OBJ_NULL) {
1470 : : // TODO: Exceptions raised in close() are not propagated,
1471 : : // printed to sys.stderr
1472 : 2 : *ret_val = mp_call_method_n_kw(0, 0, dest);
1473 : : // We assume one can't "yield" from close()
1474 : 2 : return MP_VM_RETURN_NORMAL;
1475 : : }
1476 : : } else {
1477 : 108 : mp_load_method_maybe(self_in, MP_QSTR_throw, dest);
1478 [ + + ]: 108 : if (dest[0] != MP_OBJ_NULL) {
1479 : 8 : dest[2] = throw_value;
1480 : 8 : *ret_val = mp_call_method_n_kw(1, 0, dest);
1481 : : // If .throw() method returned, we assume it's value to yield
1482 : : // - any exception would be thrown with nlr_raise().
1483 : 8 : return MP_VM_RETURN_YIELD;
1484 : : }
1485 : : }
1486 : : // If there's nowhere to throw exception into, then we assume that object
1487 : : // is just incapable to handle it, so any exception thrown into it
1488 : : // will be propagated up. This behavior is approved by test_pep380.py
1489 : : // test_delegation_of_close_to_non_generator(),
1490 : : // test_delegating_throw_to_non_generator()
1491 [ + + ]: 106 : if (mp_obj_exception_match(throw_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
1492 : : // PEP479: if StopIteration is raised inside a generator it is replaced with RuntimeError
1493 : 4 : *ret_val = mp_obj_new_exception_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("generator raised StopIteration"));
1494 : : } else {
1495 : 102 : *ret_val = mp_make_raise_obj(throw_value);
1496 : : }
1497 : : return MP_VM_RETURN_EXCEPTION;
1498 : : }
1499 : : }
1500 : :
1501 : 442437 : mp_obj_t mp_make_raise_obj(mp_obj_t o) {
1502 : 442437 : DEBUG_printf("raise %p\n", o);
1503 [ + + ]: 442437 : if (mp_obj_is_exception_type(o)) {
1504 : : // o is an exception type (it is derived from BaseException (or is BaseException))
1505 : : // create and return a new exception instance by calling o
1506 : : // TODO could have an option to disable traceback, then builtin exceptions (eg TypeError)
1507 : : // could have const instances in ROM which we return here instead
1508 : 834 : o = mp_call_function_n_kw(o, 0, 0, NULL);
1509 : : }
1510 : :
1511 [ + + ]: 442437 : if (mp_obj_is_exception_instance(o)) {
1512 : : // o is an instance of an exception, so use it as the exception
1513 : : return o;
1514 : : } else {
1515 : : // o cannot be used as an exception, so return a type error (which will be raised by the caller)
1516 : 36 : return mp_obj_new_exception_msg(&mp_type_TypeError, MP_ERROR_TEXT("exceptions must derive from BaseException"));
1517 : : }
1518 : : }
1519 : :
1520 : 2151 : mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) {
1521 : 2151 : DEBUG_printf("import name '%s' level=%d\n", qstr_str(name), MP_OBJ_SMALL_INT_VALUE(level));
1522 : :
1523 : : // build args array
1524 : 2151 : mp_obj_t args[5];
1525 : 2151 : args[0] = MP_OBJ_NEW_QSTR(name);
1526 : 2151 : args[1] = mp_const_none; // TODO should be globals
1527 : 2151 : args[2] = mp_const_none; // TODO should be locals
1528 : 2151 : args[3] = fromlist;
1529 : 2151 : args[4] = level;
1530 : :
1531 : : #if MICROPY_CAN_OVERRIDE_BUILTINS
1532 : : // Lookup __import__ and call that if it exists
1533 : 2151 : mp_obj_dict_t *bo_dict = MP_STATE_VM(mp_module_builtins_override_dict);
1534 [ + + ]: 2151 : if (bo_dict != NULL) {
1535 : 26 : mp_map_elem_t *import = mp_map_lookup(&bo_dict->map, MP_OBJ_NEW_QSTR(MP_QSTR___import__), MP_MAP_LOOKUP);
1536 [ + - ]: 26 : if (import != NULL) {
1537 : 26 : return mp_call_function_n_kw(import->value, 5, 0, args);
1538 : : }
1539 : : }
1540 : : #endif
1541 : :
1542 : 2125 : return mp_builtin___import__(5, args);
1543 : : }
1544 : :
1545 : 659 : mp_obj_t mp_import_from(mp_obj_t module, qstr name) {
1546 : 659 : DEBUG_printf("import from %p %s\n", module, qstr_str(name));
1547 : :
1548 : 659 : mp_obj_t dest[2];
1549 : :
1550 : 659 : mp_load_method_maybe(module, name, dest);
1551 : :
1552 [ - + ]: 659 : if (dest[1] != MP_OBJ_NULL) {
1553 : : // Hopefully we can't import bound method from an object
1554 : 0 : import_error:
1555 : 16 : mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("can't import name %q"), name);
1556 : : }
1557 : :
1558 [ + + ]: 659 : if (dest[0] != MP_OBJ_NULL) {
1559 : : return dest[0];
1560 : : }
1561 : :
1562 : : #if MICROPY_ENABLE_EXTERNAL_IMPORT
1563 : :
1564 : : // See if it's a package, then can try FS import
1565 : 30 : mp_load_method_maybe(module, MP_QSTR___path__, dest);
1566 [ + + ]: 30 : if (dest[0] == MP_OBJ_NULL) {
1567 : 16 : goto import_error;
1568 : : }
1569 : :
1570 : 14 : mp_load_method_maybe(module, MP_QSTR___name__, dest);
1571 : 14 : size_t pkg_name_len;
1572 : 14 : const char *pkg_name = mp_obj_str_get_data(dest[0], &pkg_name_len);
1573 : :
1574 : 14 : const uint dot_name_len = pkg_name_len + 1 + qstr_len(name);
1575 : 14 : char *dot_name = mp_local_alloc(dot_name_len);
1576 : 14 : memcpy(dot_name, pkg_name, pkg_name_len);
1577 : 14 : dot_name[pkg_name_len] = '.';
1578 : 14 : memcpy(dot_name + pkg_name_len + 1, qstr_str(name), qstr_len(name));
1579 : 14 : qstr dot_name_q = qstr_from_strn(dot_name, dot_name_len);
1580 : 14 : mp_local_free(dot_name);
1581 : :
1582 : : // For fromlist, pass sentinel "non empty" value to force returning of leaf module
1583 : 14 : return mp_import_name(dot_name_q, mp_const_true, MP_OBJ_NEW_SMALL_INT(0));
1584 : :
1585 : : #else
1586 : :
1587 : : // Package import not supported with external imports disabled
1588 : : goto import_error;
1589 : :
1590 : : #endif
1591 : : }
1592 : :
1593 : 110 : void mp_import_all(mp_obj_t module) {
1594 : 110 : DEBUG_printf("import all %p\n", module);
1595 : :
1596 : : // TODO: Support __all__
1597 : 110 : mp_map_t *map = &mp_obj_module_get_globals(module)->map;
1598 [ + + ]: 2698 : for (size_t i = 0; i < map->alloc; i++) {
1599 [ + + ]: 2588 : if (mp_map_slot_is_filled(map, i)) {
1600 : : // Entry in module global scope may be generated programmatically
1601 : : // (and thus be not a qstr for longer names). Avoid turning it in
1602 : : // qstr if it has '_' and was used exactly to save memory.
1603 : 2586 : const char *name = mp_obj_str_get_str(map->table[i].key);
1604 [ + + ]: 2586 : if (*name != '_') {
1605 : 2032 : qstr qname = mp_obj_str_get_qstr(map->table[i].key);
1606 : 2032 : mp_store_name(qname, map->table[i].value);
1607 : : }
1608 : : }
1609 : : }
1610 : 110 : }
1611 : :
1612 : : #if MICROPY_ENABLE_COMPILER
1613 : :
1614 : 1764 : mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_input_kind, mp_obj_dict_t *globals, mp_obj_dict_t *locals) {
1615 : : // save context
1616 : 1764 : nlr_jump_callback_node_globals_locals_t ctx;
1617 : 1764 : ctx.globals = mp_globals_get();
1618 : 1765 : ctx.locals = mp_locals_get();
1619 : :
1620 : : // set new context
1621 : 1765 : mp_globals_set(globals);
1622 : 1765 : mp_locals_set(locals);
1623 : :
1624 : : // set exception handler to restore context if an exception is raised
1625 : 1765 : nlr_push_jump_callback(&ctx.callback, mp_globals_locals_set_from_nlr_jump_callback);
1626 : :
1627 : 1765 : qstr source_name = lex->source_name;
1628 : 1765 : mp_parse_tree_t parse_tree = mp_parse(lex, parse_input_kind);
1629 : 1627 : mp_obj_t module_fun = mp_compile(&parse_tree, source_name, parse_input_kind == MP_PARSE_SINGLE_INPUT);
1630 : :
1631 : 1291 : mp_obj_t ret;
1632 : : #if MICROPY_PY_BUILTINS_COMPILE && MICROPY_PY_BUILTINS_CODE == MICROPY_PY_BUILTINS_CODE_MINIMUM
1633 : : if (globals == NULL) {
1634 : : // for compile only, return value is the module function
1635 : : ret = module_fun;
1636 : : } else
1637 : : #endif
1638 : : {
1639 : : // execute module function and get return value
1640 : 1291 : ret = mp_call_function_0(module_fun);
1641 : : }
1642 : :
1643 : : // deregister exception handler and restore context
1644 : 1213 : nlr_pop_jump_callback(true);
1645 : :
1646 : : // return value
1647 : 1213 : return ret;
1648 : : }
1649 : :
1650 : : #endif // MICROPY_ENABLE_COMPILER
1651 : :
1652 : 110 : NORETURN void m_malloc_fail(size_t num_bytes) {
1653 : 110 : DEBUG_printf("memory allocation failed, allocating %u bytes\n", (uint)num_bytes);
1654 : : #if MICROPY_ENABLE_GC
1655 [ + + ]: 110 : if (gc_is_locked()) {
1656 : 94 : mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("memory allocation failed, heap is locked"));
1657 : : }
1658 : : #endif
1659 : 16 : mp_raise_msg_varg(&mp_type_MemoryError,
1660 : 16 : MP_ERROR_TEXT("memory allocation failed, allocating %u bytes"), (uint)num_bytes);
1661 : : }
1662 : :
1663 : : #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NONE
1664 : :
1665 : : NORETURN void mp_raise_type(const mp_obj_type_t *exc_type) {
1666 : : nlr_raise(mp_obj_new_exception(exc_type));
1667 : : }
1668 : :
1669 : : NORETURN void mp_raise_ValueError_no_msg(void) {
1670 : : mp_raise_type(&mp_type_ValueError);
1671 : : }
1672 : :
1673 : : NORETURN void mp_raise_TypeError_no_msg(void) {
1674 : : mp_raise_type(&mp_type_TypeError);
1675 : : }
1676 : :
1677 : : NORETURN void mp_raise_NotImplementedError_no_msg(void) {
1678 : : mp_raise_type(&mp_type_NotImplementedError);
1679 : : }
1680 : :
1681 : : #else
1682 : :
1683 : 8232 : NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg) {
1684 [ + + ]: 8232 : if (msg == NULL) {
1685 : 1089 : nlr_raise(mp_obj_new_exception(exc_type));
1686 : : } else {
1687 : 7143 : nlr_raise(mp_obj_new_exception_msg(exc_type, msg));
1688 : : }
1689 : : }
1690 : :
1691 : 1232 : NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, ...) {
1692 : 1232 : va_list args;
1693 : 1232 : va_start(args, fmt);
1694 : 1232 : mp_obj_t exc = mp_obj_new_exception_msg_vlist(exc_type, fmt, args);
1695 : 1232 : va_end(args);
1696 : 1232 : nlr_raise(exc);
1697 : : }
1698 : :
1699 : 1073 : NORETURN void mp_raise_ValueError(mp_rom_error_text_t msg) {
1700 : 1073 : mp_raise_msg(&mp_type_ValueError, msg);
1701 : : }
1702 : :
1703 : 305 : NORETURN void mp_raise_TypeError(mp_rom_error_text_t msg) {
1704 : 305 : mp_raise_msg(&mp_type_TypeError, msg);
1705 : : }
1706 : :
1707 : 412 : NORETURN void mp_raise_NotImplementedError(mp_rom_error_text_t msg) {
1708 : 412 : mp_raise_msg(&mp_type_NotImplementedError, msg);
1709 : : }
1710 : :
1711 : : #endif
1712 : :
1713 : 635 : NORETURN void mp_raise_type_arg(const mp_obj_type_t *exc_type, mp_obj_t arg) {
1714 : 635 : nlr_raise(mp_obj_new_exception_arg1(exc_type, arg));
1715 : : }
1716 : :
1717 : 616 : NORETURN void mp_raise_StopIteration(mp_obj_t arg) {
1718 [ + + ]: 616 : if (arg == MP_OBJ_NULL) {
1719 : 528 : mp_raise_type(&mp_type_StopIteration);
1720 : : } else {
1721 : 88 : mp_raise_type_arg(&mp_type_StopIteration, arg);
1722 : : }
1723 : : }
1724 : :
1725 : 40 : NORETURN void mp_raise_TypeError_int_conversion(mp_const_obj_t arg) {
1726 : : #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
1727 : : (void)arg;
1728 : : mp_raise_TypeError(MP_ERROR_TEXT("can't convert to int"));
1729 : : #else
1730 : 40 : mp_raise_msg_varg(&mp_type_TypeError,
1731 : 40 : MP_ERROR_TEXT("can't convert %s to int"), mp_obj_get_type_str(arg));
1732 : : #endif
1733 : : }
1734 : :
1735 : 382 : NORETURN void mp_raise_OSError(int errno_) {
1736 : 382 : mp_raise_type_arg(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno_));
1737 : : }
1738 : :
1739 : 0 : NORETURN void mp_raise_OSError_with_filename(int errno_, const char *filename) {
1740 : 0 : vstr_t vstr;
1741 : 0 : vstr_init(&vstr, 32);
1742 : 0 : vstr_printf(&vstr, "can't open %s", filename);
1743 : 0 : mp_obj_t o_str = mp_obj_new_str_from_vstr(&vstr);
1744 : 0 : mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(errno_), MP_OBJ_FROM_PTR(o_str)};
1745 : 0 : nlr_raise(mp_obj_exception_make_new(&mp_type_OSError, 2, 0, args));
1746 : : }
1747 : :
1748 : : #if MICROPY_STACK_CHECK || MICROPY_ENABLE_PYSTACK
1749 : 23 : NORETURN void mp_raise_recursion_depth(void) {
1750 : 23 : mp_raise_type_arg(&mp_type_RuntimeError, MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded));
1751 : : }
1752 : : #endif
|