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 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdarg.h>
30 #include <assert.h>
31
32 #include "py/obj.h"
33 #include "py/objtype.h"
34 #include "py/objint.h"
35 #include "py/objstr.h"
36 #include "py/runtime.h"
37 #include "py/stackctrl.h"
38 #include "py/stream.h" // for mp_obj_print
39
mp_obj_get_type(mp_const_obj_t o_in)40 const mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) {
41 #if MICROPY_OBJ_IMMEDIATE_OBJS && MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A
42
43 if (mp_obj_is_obj(o_in)) {
44 const mp_obj_base_t *o = MP_OBJ_TO_PTR(o_in);
45 return o->type;
46 } else {
47 static const mp_obj_type_t *const types[] = {
48 NULL, &mp_type_int, &mp_type_str, &mp_type_int,
49 NULL, &mp_type_int, &mp_type_NoneType, &mp_type_int,
50 NULL, &mp_type_int, &mp_type_str, &mp_type_int,
51 NULL, &mp_type_int, &mp_type_bool, &mp_type_int,
52 };
53 return types[(uintptr_t)o_in & 0xf];
54 }
55
56 #elif MICROPY_OBJ_IMMEDIATE_OBJS && MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C
57
58 if (mp_obj_is_small_int(o_in)) {
59 return &mp_type_int;
60 } else if (mp_obj_is_obj(o_in)) {
61 const mp_obj_base_t *o = MP_OBJ_TO_PTR(o_in);
62 return o->type;
63 #if MICROPY_PY_BUILTINS_FLOAT
64 } else if ((((mp_uint_t)(o_in)) & 0xff800007) != 0x00000006) {
65 return &mp_type_float;
66 #endif
67 } else {
68 static const mp_obj_type_t *const types[] = {
69 &mp_type_str, &mp_type_NoneType, &mp_type_str, &mp_type_bool,
70 };
71 return types[((uintptr_t)o_in >> 3) & 3];
72 }
73
74 #else
75
76 if (mp_obj_is_small_int(o_in)) {
77 return &mp_type_int;
78 } else if (mp_obj_is_qstr(o_in)) {
79 return &mp_type_str;
80 #if MICROPY_PY_BUILTINS_FLOAT && ( \
81 MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D)
82 } else if (mp_obj_is_float(o_in)) {
83 return &mp_type_float;
84 #endif
85 #if MICROPY_OBJ_IMMEDIATE_OBJS
86 } else if (mp_obj_is_immediate_obj(o_in)) {
87 static const mp_obj_type_t *const types[2] = {&mp_type_NoneType, &mp_type_bool};
88 return types[MP_OBJ_IMMEDIATE_OBJ_VALUE(o_in) & 1];
89 #endif
90 } else {
91 const mp_obj_base_t *o = MP_OBJ_TO_PTR(o_in);
92 return o->type;
93 }
94
95 #endif
96 }
97
mp_obj_get_type_str(mp_const_obj_t o_in)98 const char *mp_obj_get_type_str(mp_const_obj_t o_in) {
99 return qstr_str(mp_obj_get_type(o_in)->name);
100 }
101
mp_obj_print_helper(const mp_print_t * print,mp_obj_t o_in,mp_print_kind_t kind)102 void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
103 // There can be data structures nested too deep, or just recursive
104 MP_STACK_CHECK();
105 #ifndef NDEBUG
106 if (o_in == MP_OBJ_NULL) {
107 mp_print_str(print, "(nil)");
108 return;
109 }
110 #endif
111 const mp_obj_type_t *type = mp_obj_get_type(o_in);
112 if (type->print != NULL) {
113 type->print((mp_print_t *)print, o_in, kind);
114 } else {
115 mp_printf(print, "<%q>", type->name);
116 }
117 }
118
mp_obj_print(mp_obj_t o_in,mp_print_kind_t kind)119 void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) {
120 mp_obj_print_helper(MP_PYTHON_PRINTER, o_in, kind);
121 }
122
123 // helper function to print an exception with traceback
mp_obj_print_exception(const mp_print_t * print,mp_obj_t exc)124 void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc) {
125 if (mp_obj_is_exception_instance(exc)) {
126 size_t n, *values;
127 mp_obj_exception_get_traceback(exc, &n, &values);
128 if (n > 0) {
129 assert(n % 3 == 0);
130 mp_print_str(print, "Traceback (most recent call last):\n");
131 for (int i = n - 3; i >= 0; i -= 3) {
132 #if MICROPY_ENABLE_SOURCE_LINE
133 mp_printf(print, " File \"%q\", line %d", values[i], (int)values[i + 1]);
134 #else
135 mp_printf(print, " File \"%q\"", values[i]);
136 #endif
137 // the block name can be NULL if it's unknown
138 qstr block = values[i + 2];
139 if (block == MP_QSTRnull) {
140 mp_print_str(print, "\n");
141 } else {
142 mp_printf(print, ", in %q\n", block);
143 }
144 }
145 }
146 }
147 mp_obj_print_helper(print, exc, PRINT_EXC);
148 mp_print_str(print, "\n");
149 }
150
mp_obj_is_true(mp_obj_t arg)151 bool mp_obj_is_true(mp_obj_t arg) {
152 if (arg == mp_const_false) {
153 return 0;
154 } else if (arg == mp_const_true) {
155 return 1;
156 } else if (arg == mp_const_none) {
157 return 0;
158 } else if (mp_obj_is_small_int(arg)) {
159 if (arg == MP_OBJ_NEW_SMALL_INT(0)) {
160 return 0;
161 } else {
162 return 1;
163 }
164 } else {
165 const mp_obj_type_t *type = mp_obj_get_type(arg);
166 if (type->unary_op != NULL) {
167 mp_obj_t result = type->unary_op(MP_UNARY_OP_BOOL, arg);
168 if (result != MP_OBJ_NULL) {
169 return result == mp_const_true;
170 }
171 }
172
173 mp_obj_t len = mp_obj_len_maybe(arg);
174 if (len != MP_OBJ_NULL) {
175 // obj has a length, truth determined if len != 0
176 return len != MP_OBJ_NEW_SMALL_INT(0);
177 } else {
178 // any other obj is true per Python semantics
179 return 1;
180 }
181 }
182 }
183
mp_obj_is_callable(mp_obj_t o_in)184 bool mp_obj_is_callable(mp_obj_t o_in) {
185 const mp_call_fun_t call = mp_obj_get_type(o_in)->call;
186 if (call != mp_obj_instance_call) {
187 return call != NULL;
188 }
189 return mp_obj_instance_is_callable(o_in);
190 }
191
192 // This function implements the '==' and '!=' operators.
193 //
194 // From the Python language reference:
195 // (https://docs.python.org/3/reference/expressions.html#not-in)
196 // "The objects need not have the same type. If both are numbers, they are converted
197 // to a common type. Otherwise, the == and != operators always consider objects of
198 // different types to be unequal."
199 //
200 // This means that False==0 and True==1 are true expressions.
201 //
202 // Furthermore, from the v3.4.2 code for object.c: "Practical amendments: If rich
203 // comparison returns NotImplemented, == and != are decided by comparing the object
204 // pointer."
mp_obj_equal_not_equal(mp_binary_op_t op,mp_obj_t o1,mp_obj_t o2)205 mp_obj_t mp_obj_equal_not_equal(mp_binary_op_t op, mp_obj_t o1, mp_obj_t o2) {
206 mp_obj_t local_true = (op == MP_BINARY_OP_NOT_EQUAL) ? mp_const_false : mp_const_true;
207 mp_obj_t local_false = (op == MP_BINARY_OP_NOT_EQUAL) ? mp_const_true : mp_const_false;
208 int pass_number = 0;
209
210 // Shortcut for very common cases
211 if (o1 == o2 &&
212 (mp_obj_is_small_int(o1) || !(mp_obj_get_type(o1)->flags & MP_TYPE_FLAG_EQ_NOT_REFLEXIVE))) {
213 return local_true;
214 }
215
216 // fast path for strings
217 if (mp_obj_is_str(o1)) {
218 if (mp_obj_is_str(o2)) {
219 // both strings, use special function
220 return mp_obj_str_equal(o1, o2) ? local_true : local_false;
221 #if MICROPY_PY_STR_BYTES_CMP_WARN
222 } else if (mp_obj_is_type(o2, &mp_type_bytes)) {
223 str_bytes_cmp:
224 mp_warning(MP_WARN_CAT(BytesWarning), "Comparison between bytes and str");
225 return local_false;
226 #endif
227 } else {
228 goto skip_one_pass;
229 }
230 #if MICROPY_PY_STR_BYTES_CMP_WARN
231 } else if (mp_obj_is_str(o2) && mp_obj_is_type(o1, &mp_type_bytes)) {
232 // o1 is not a string (else caught above), so the objects are not equal
233 goto str_bytes_cmp;
234 #endif
235 }
236
237 // fast path for small ints
238 if (mp_obj_is_small_int(o1)) {
239 if (mp_obj_is_small_int(o2)) {
240 // both SMALL_INT, and not equal if we get here
241 return local_false;
242 } else {
243 goto skip_one_pass;
244 }
245 }
246
247 // generic type, call binary_op(MP_BINARY_OP_EQUAL)
248 while (pass_number < 2) {
249 const mp_obj_type_t *type = mp_obj_get_type(o1);
250 // If a full equality test is not needed and the other object is a different
251 // type then we don't need to bother trying the comparison.
252 if (type->binary_op != NULL &&
253 ((type->flags & MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE) || mp_obj_get_type(o2) == type)) {
254 // CPython is asymmetric: it will try __eq__ if there's no __ne__ but not the
255 // other way around. If the class doesn't need a full test we can skip __ne__.
256 if (op == MP_BINARY_OP_NOT_EQUAL && (type->flags & MP_TYPE_FLAG_EQ_HAS_NEQ_TEST)) {
257 mp_obj_t r = type->binary_op(MP_BINARY_OP_NOT_EQUAL, o1, o2);
258 if (r != MP_OBJ_NULL) {
259 return r;
260 }
261 }
262
263 // Try calling __eq__.
264 mp_obj_t r = type->binary_op(MP_BINARY_OP_EQUAL, o1, o2);
265 if (r != MP_OBJ_NULL) {
266 if (op == MP_BINARY_OP_EQUAL) {
267 return r;
268 } else {
269 return mp_obj_is_true(r) ? local_true : local_false;
270 }
271 }
272 }
273
274 skip_one_pass:
275 // Try the other way around if none of the above worked
276 ++pass_number;
277 mp_obj_t temp = o1;
278 o1 = o2;
279 o2 = temp;
280 }
281
282 // equality not implemented, so fall back to pointer conparison
283 return (o1 == o2) ? local_true : local_false;
284 }
285
mp_obj_equal(mp_obj_t o1,mp_obj_t o2)286 bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
287 return mp_obj_is_true(mp_obj_equal_not_equal(MP_BINARY_OP_EQUAL, o1, o2));
288 }
289
mp_obj_get_int(mp_const_obj_t arg)290 mp_int_t mp_obj_get_int(mp_const_obj_t arg) {
291 // This function essentially performs implicit type conversion to int
292 // Note that Python does NOT provide implicit type conversion from
293 // float to int in the core expression language, try some_list[1.0].
294 if (arg == mp_const_false) {
295 return 0;
296 } else if (arg == mp_const_true) {
297 return 1;
298 } else if (mp_obj_is_small_int(arg)) {
299 return MP_OBJ_SMALL_INT_VALUE(arg);
300 } else if (mp_obj_is_type(arg, &mp_type_int)) {
301 return mp_obj_int_get_checked(arg);
302 } else {
303 mp_obj_t res = mp_unary_op(MP_UNARY_OP_INT, (mp_obj_t)arg);
304 return mp_obj_int_get_checked(res);
305 }
306 }
307
mp_obj_get_int_truncated(mp_const_obj_t arg)308 mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg) {
309 if (mp_obj_is_int(arg)) {
310 return mp_obj_int_get_truncated(arg);
311 } else {
312 return mp_obj_get_int(arg);
313 }
314 }
315
316 // returns false if arg is not of integral type
317 // returns true and sets *value if it is of integral type
318 // can throw OverflowError if arg is of integral type, but doesn't fit in a mp_int_t
mp_obj_get_int_maybe(mp_const_obj_t arg,mp_int_t * value)319 bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value) {
320 if (arg == mp_const_false) {
321 *value = 0;
322 } else if (arg == mp_const_true) {
323 *value = 1;
324 } else if (mp_obj_is_small_int(arg)) {
325 *value = MP_OBJ_SMALL_INT_VALUE(arg);
326 } else if (mp_obj_is_type(arg, &mp_type_int)) {
327 *value = mp_obj_int_get_checked(arg);
328 } else {
329 return false;
330 }
331 return true;
332 }
333
334 #if MICROPY_PY_BUILTINS_FLOAT
mp_obj_get_float_maybe(mp_obj_t arg,mp_float_t * value)335 bool mp_obj_get_float_maybe(mp_obj_t arg, mp_float_t *value) {
336 mp_float_t val;
337
338 if (arg == mp_const_false) {
339 val = 0;
340 } else if (arg == mp_const_true) {
341 val = 1;
342 } else if (mp_obj_is_small_int(arg)) {
343 val = (mp_float_t)MP_OBJ_SMALL_INT_VALUE(arg);
344 #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
345 } else if (mp_obj_is_type(arg, &mp_type_int)) {
346 val = mp_obj_int_as_float_impl(arg);
347 #endif
348 } else if (mp_obj_is_float(arg)) {
349 val = mp_obj_float_get(arg);
350 } else {
351 return false;
352 }
353
354 *value = val;
355 return true;
356 }
357
mp_obj_get_float(mp_obj_t arg)358 mp_float_t mp_obj_get_float(mp_obj_t arg) {
359 mp_float_t val;
360
361 if (!mp_obj_get_float_maybe(arg, &val)) {
362 #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
363 mp_raise_TypeError(MP_ERROR_TEXT("can't convert to float"));
364 #else
365 mp_raise_msg_varg(&mp_type_TypeError,
366 MP_ERROR_TEXT("can't convert %s to float"), mp_obj_get_type_str(arg));
367 #endif
368 }
369
370 return val;
371 }
372
373 #if MICROPY_PY_BUILTINS_COMPLEX
mp_obj_get_complex_maybe(mp_obj_t arg,mp_float_t * real,mp_float_t * imag)374 bool mp_obj_get_complex_maybe(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
375 if (arg == mp_const_false) {
376 *real = 0;
377 *imag = 0;
378 } else if (arg == mp_const_true) {
379 *real = 1;
380 *imag = 0;
381 } else if (mp_obj_is_small_int(arg)) {
382 *real = (mp_float_t)MP_OBJ_SMALL_INT_VALUE(arg);
383 *imag = 0;
384 #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
385 } else if (mp_obj_is_type(arg, &mp_type_int)) {
386 *real = mp_obj_int_as_float_impl(arg);
387 *imag = 0;
388 #endif
389 } else if (mp_obj_is_float(arg)) {
390 *real = mp_obj_float_get(arg);
391 *imag = 0;
392 } else if (mp_obj_is_type(arg, &mp_type_complex)) {
393 mp_obj_complex_get(arg, real, imag);
394 } else {
395 return false;
396 }
397 return true;
398 }
399
mp_obj_get_complex(mp_obj_t arg,mp_float_t * real,mp_float_t * imag)400 void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
401 if (!mp_obj_get_complex_maybe(arg, real, imag)) {
402 #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
403 mp_raise_TypeError(MP_ERROR_TEXT("can't convert to complex"));
404 #else
405 mp_raise_msg_varg(&mp_type_TypeError,
406 MP_ERROR_TEXT("can't convert %s to complex"), mp_obj_get_type_str(arg));
407 #endif
408 }
409 }
410 #endif
411 #endif
412
413 // note: returned value in *items may point to the interior of a GC block
mp_obj_get_array(mp_obj_t o,size_t * len,mp_obj_t ** items)414 void mp_obj_get_array(mp_obj_t o, size_t *len, mp_obj_t **items) {
415 if (mp_obj_is_type(o, &mp_type_tuple)) {
416 mp_obj_tuple_get(o, len, items);
417 } else if (mp_obj_is_type(o, &mp_type_list)) {
418 mp_obj_list_get(o, len, items);
419 } else {
420 #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
421 mp_raise_TypeError(MP_ERROR_TEXT("expected tuple/list"));
422 #else
423 mp_raise_msg_varg(&mp_type_TypeError,
424 MP_ERROR_TEXT("object '%s' isn't a tuple or list"), mp_obj_get_type_str(o));
425 #endif
426 }
427 }
428
429 // note: returned value in *items may point to the interior of a GC block
mp_obj_get_array_fixed_n(mp_obj_t o,size_t len,mp_obj_t ** items)430 void mp_obj_get_array_fixed_n(mp_obj_t o, size_t len, mp_obj_t **items) {
431 size_t seq_len;
432 mp_obj_get_array(o, &seq_len, items);
433 if (seq_len != len) {
434 #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
435 mp_raise_ValueError(MP_ERROR_TEXT("tuple/list has wrong length"));
436 #else
437 mp_raise_msg_varg(&mp_type_ValueError,
438 MP_ERROR_TEXT("requested length %d but object has length %d"), (int)len, (int)seq_len);
439 #endif
440 }
441 }
442
443 // is_slice determines whether the index is a slice index
mp_get_index(const mp_obj_type_t * type,size_t len,mp_obj_t index,bool is_slice)444 size_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool is_slice) {
445 mp_int_t i;
446 if (mp_obj_is_small_int(index)) {
447 i = MP_OBJ_SMALL_INT_VALUE(index);
448 } else if (!mp_obj_get_int_maybe(index, &i)) {
449 #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
450 mp_raise_TypeError(MP_ERROR_TEXT("indices must be integers"));
451 #else
452 mp_raise_msg_varg(&mp_type_TypeError,
453 MP_ERROR_TEXT("%q indices must be integers, not %s"),
454 type->name, mp_obj_get_type_str(index));
455 #endif
456 }
457
458 if (i < 0) {
459 i += len;
460 }
461 if (is_slice) {
462 if (i < 0) {
463 i = 0;
464 } else if ((mp_uint_t)i > len) {
465 i = len;
466 }
467 } else {
468 if (i < 0 || (mp_uint_t)i >= len) {
469 #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
470 mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("index out of range"));
471 #else
472 mp_raise_msg_varg(&mp_type_IndexError, MP_ERROR_TEXT("%q index out of range"), type->name);
473 #endif
474 }
475 }
476
477 // By this point 0 <= i <= len and so fits in a size_t
478 return (size_t)i;
479 }
480
mp_obj_id(mp_obj_t o_in)481 mp_obj_t mp_obj_id(mp_obj_t o_in) {
482 mp_int_t id = (mp_int_t)o_in;
483 if (!mp_obj_is_obj(o_in)) {
484 return mp_obj_new_int(id);
485 } else if (id >= 0) {
486 // Many OSes and CPUs have affinity for putting "user" memories
487 // into low half of address space, and "system" into upper half.
488 // We're going to take advantage of that and return small int
489 // (signed) for such "user" addresses.
490 return MP_OBJ_NEW_SMALL_INT(id);
491 } else {
492 // If that didn't work, well, let's return long int, just as
493 // a (big) positive value, so it will never clash with the range
494 // of small int returned in previous case.
495 return mp_obj_new_int_from_uint((mp_uint_t)id);
496 }
497 }
498
499 // will raise a TypeError if object has no length
mp_obj_len(mp_obj_t o_in)500 mp_obj_t mp_obj_len(mp_obj_t o_in) {
501 mp_obj_t len = mp_obj_len_maybe(o_in);
502 if (len == MP_OBJ_NULL) {
503 #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
504 mp_raise_TypeError(MP_ERROR_TEXT("object has no len"));
505 #else
506 mp_raise_msg_varg(&mp_type_TypeError,
507 MP_ERROR_TEXT("object of type '%s' has no len()"), mp_obj_get_type_str(o_in));
508 #endif
509 } else {
510 return len;
511 }
512 }
513
514 // may return MP_OBJ_NULL
mp_obj_len_maybe(mp_obj_t o_in)515 mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {
516 if (
517 #if !MICROPY_PY_BUILTINS_STR_UNICODE
518 // It's simple - unicode is slow, non-unicode is fast
519 mp_obj_is_str(o_in) ||
520 #endif
521 mp_obj_is_type(o_in, &mp_type_bytes)) {
522 GET_STR_LEN(o_in, l);
523 return MP_OBJ_NEW_SMALL_INT(l);
524 } else {
525 const mp_obj_type_t *type = mp_obj_get_type(o_in);
526 if (type->unary_op != NULL) {
527 return type->unary_op(MP_UNARY_OP_LEN, o_in);
528 } else {
529 return MP_OBJ_NULL;
530 }
531 }
532 }
533
mp_obj_subscr(mp_obj_t base,mp_obj_t index,mp_obj_t value)534 mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) {
535 const mp_obj_type_t *type = mp_obj_get_type(base);
536 if (type->subscr != NULL) {
537 mp_obj_t ret = type->subscr(base, index, value);
538 if (ret != MP_OBJ_NULL) {
539 return ret;
540 }
541 // TODO: call base classes here?
542 }
543 if (value == MP_OBJ_NULL) {
544 #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
545 mp_raise_TypeError(MP_ERROR_TEXT("object doesn't support item deletion"));
546 #else
547 mp_raise_msg_varg(&mp_type_TypeError,
548 MP_ERROR_TEXT("'%s' object doesn't support item deletion"), mp_obj_get_type_str(base));
549 #endif
550 } else if (value == MP_OBJ_SENTINEL) {
551 #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
552 mp_raise_TypeError(MP_ERROR_TEXT("object isn't subscriptable"));
553 #else
554 mp_raise_msg_varg(&mp_type_TypeError,
555 MP_ERROR_TEXT("'%s' object isn't subscriptable"), mp_obj_get_type_str(base));
556 #endif
557 } else {
558 #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
559 mp_raise_TypeError(MP_ERROR_TEXT("object doesn't support item assignment"));
560 #else
561 mp_raise_msg_varg(&mp_type_TypeError,
562 MP_ERROR_TEXT("'%s' object doesn't support item assignment"), mp_obj_get_type_str(base));
563 #endif
564 }
565 }
566
567 // Return input argument. Useful as .getiter for objects which are
568 // their own iterators, etc.
mp_identity(mp_obj_t self)569 mp_obj_t mp_identity(mp_obj_t self) {
570 return self;
571 }
572 MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity);
573
mp_identity_getiter(mp_obj_t self,mp_obj_iter_buf_t * iter_buf)574 mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf) {
575 (void)iter_buf;
576 return self;
577 }
578
mp_get_buffer(mp_obj_t obj,mp_buffer_info_t * bufinfo,mp_uint_t flags)579 bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
580 const mp_obj_type_t *type = mp_obj_get_type(obj);
581 if (type->buffer_p.get_buffer == NULL) {
582 return false;
583 }
584 int ret = type->buffer_p.get_buffer(obj, bufinfo, flags);
585 if (ret != 0) {
586 return false;
587 }
588 return true;
589 }
590
mp_get_buffer_raise(mp_obj_t obj,mp_buffer_info_t * bufinfo,mp_uint_t flags)591 void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
592 if (!mp_get_buffer(obj, bufinfo, flags)) {
593 mp_raise_TypeError(MP_ERROR_TEXT("object with buffer protocol required"));
594 }
595 }
596
mp_generic_unary_op(mp_unary_op_t op,mp_obj_t o_in)597 mp_obj_t mp_generic_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
598 switch (op) {
599 case MP_UNARY_OP_HASH:
600 return MP_OBJ_NEW_SMALL_INT((mp_uint_t)o_in);
601 default:
602 return MP_OBJ_NULL; // op not supported
603 }
604 }
605