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