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