1/*
2 * This file is part of the MicroPython project, http://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2013-2018 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 <stdio.h>
29#include <stddef.h>
30#include <string.h>
31#include <assert.h>
32
33#include "py/objtype.h"
34#include "py/runtime.h"
35
36#if MICROPY_DEBUG_VERBOSE // print debugging info
37#define DEBUG_PRINT (1)
38#define DEBUG_printf DEBUG_printf
39#else // don't print debugging info
40#define DEBUG_PRINT (0)
41#define DEBUG_printf(...) (void)0
42#endif
43
44#define ENABLE_SPECIAL_ACCESSORS \
45 (MICROPY_PY_DESCRIPTORS || MICROPY_PY_DELATTR_SETATTR || MICROPY_PY_BUILTINS_PROPERTY)
46
47STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self_in, size_t n_args, size_t n_kw, const mp_obj_t *args);
48
49/******************************************************************************/
50// instance object
51
52STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) {
53 int count = 0;
54 for (;;) {
55 if (type == &mp_type_object) {
56 // Not a "real" type, end search here.
57 return count;
58 } else if (mp_obj_is_native_type(type)) {
59 // Native types don't have parents (at least not from our perspective) so end.
60 *last_native_base = type;
61 return count + 1;
62 } else if (type->parent == NULL) {
63 // No parents so end search here.
64 return count;
65 #if MICROPY_MULTIPLE_INHERITANCE
66 } else if (((mp_obj_base_t *)type->parent)->type == &mp_type_tuple) {
67 // Multiple parents, search through them all recursively.
68 const mp_obj_tuple_t *parent_tuple = type->parent;
69 const mp_obj_t *item = parent_tuple->items;
70 const mp_obj_t *top = item + parent_tuple->len;
71 for (; item < top; ++item) {
72 assert(mp_obj_is_type(*item, &mp_type_type));
73 const mp_obj_type_t *bt = (const mp_obj_type_t *)MP_OBJ_TO_PTR(*item);
74 count += instance_count_native_bases(bt, last_native_base);
75 }
76 return count;
77 #endif
78 } else {
79 // A single parent, use iteration to continue the search.
80 type = type->parent;
81 }
82 }
83}
84
85// This wrapper function is allows a subclass of a native type to call the
86// __init__() method (corresponding to type->make_new) of the native type.
87STATIC mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *args) {
88 mp_obj_instance_t *self = MP_OBJ_TO_PTR(args[0]);
89 const mp_obj_type_t *native_base = NULL;
90 instance_count_native_bases(self->base.type, &native_base);
91 self->subobj[0] = native_base->make_new(native_base, n_args - 1, 0, args + 1);
92 return mp_const_none;
93}
94STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(native_base_init_wrapper_obj, 1, MP_OBJ_FUN_ARGS_MAX, native_base_init_wrapper);
95
96#if !MICROPY_CPYTHON_COMPAT
97STATIC
98#endif
99mp_obj_instance_t *mp_obj_new_instance(const mp_obj_type_t *class, const mp_obj_type_t **native_base) {
100 size_t num_native_bases = instance_count_native_bases(class, native_base);
101 assert(num_native_bases < 2);
102 mp_obj_instance_t *o = m_new_obj_var(mp_obj_instance_t, mp_obj_t, num_native_bases);
103 o->base.type = class;
104 mp_map_init(&o->members, 0);
105 // Initialise the native base-class slot (should be 1 at most) with a valid
106 // object. It doesn't matter which object, so long as it can be uniquely
107 // distinguished from a native class that is initialised.
108 if (num_native_bases != 0) {
109 o->subobj[0] = MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj);
110 }
111 return o;
112}
113
114// TODO
115// This implements depth-first left-to-right MRO, which is not compliant with Python3 MRO
116// http://python-history.blogspot.com/2010/06/method-resolution-order.html
117// https://www.python.org/download/releases/2.3/mro/
118//
119// will keep lookup->dest[0]'s value (should be MP_OBJ_NULL on invocation) if attribute
120// is not found
121// will set lookup->dest[0] to MP_OBJ_SENTINEL if special method was found in a native
122// type base via slot id (as specified by lookup->meth_offset). As there can be only one
123// native base, it's known that it applies to instance->subobj[0]. In most cases, we also
124// don't need to know which type it was - because instance->subobj[0] is of that type.
125// The only exception is when object is not yet constructed, then we need to know base
126// native type to construct its instance->subobj[0] from. But this case is handled via
127// instance_count_native_bases(), which returns a native base which it saw.
128struct class_lookup_data {
129 mp_obj_instance_t *obj;
130 qstr attr;
131 size_t meth_offset;
132 mp_obj_t *dest;
133 bool is_type;
134};
135
136STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_type_t *type) {
137 assert(lookup->dest[0] == MP_OBJ_NULL);
138 assert(lookup->dest[1] == MP_OBJ_NULL);
139 for (;;) {
140 DEBUG_printf("mp_obj_class_lookup: Looking up %s in %s\n", qstr_str(lookup->attr), qstr_str(type->name));
141 // Optimize special method lookup for native types
142 // This avoids extra method_name => slot lookup. On the other hand,
143 // this should not be applied to class types, as will result in extra
144 // lookup either.
145 if (lookup->meth_offset != 0 && mp_obj_is_native_type(type)) {
146 if (*(void **)((char *)type + lookup->meth_offset) != NULL) {
147 DEBUG_printf("mp_obj_class_lookup: Matched special meth slot (off=%d) for %s\n",
148 lookup->meth_offset, qstr_str(lookup->attr));
149 lookup->dest[0] = MP_OBJ_SENTINEL;
150 return;
151 }
152 }
153
154 if (type->locals_dict != NULL) {
155 // search locals_dict (the set of methods/attributes)
156 assert(mp_obj_is_dict_or_ordereddict(MP_OBJ_FROM_PTR(type->locals_dict))); // MicroPython restriction, for now
157 mp_map_t *locals_map = &type->locals_dict->map;
158 mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(lookup->attr), MP_MAP_LOOKUP);
159 if (elem != NULL) {
160 if (lookup->is_type) {
161 // If we look up a class method, we need to return original type for which we
162 // do a lookup, not a (base) type in which we found the class method.
163 const mp_obj_type_t *org_type = (const mp_obj_type_t *)lookup->obj;
164 mp_convert_member_lookup(MP_OBJ_NULL, org_type, elem->value, lookup->dest);
165 } else {
166 mp_obj_instance_t *obj = lookup->obj;
167 mp_obj_t obj_obj;
168 if (obj != NULL && mp_obj_is_native_type(type) && type != &mp_type_object /* object is not a real type */) {
169 // If we're dealing with native base class, then it applies to native sub-object
170 obj_obj = obj->subobj[0];
171 } else {
172 obj_obj = MP_OBJ_FROM_PTR(obj);
173 }
174 mp_convert_member_lookup(obj_obj, type, elem->value, lookup->dest);
175 }
176 #if DEBUG_PRINT
177 DEBUG_printf("mp_obj_class_lookup: Returning: ");
178 mp_obj_print_helper(MICROPY_DEBUG_PRINTER, lookup->dest[0], PRINT_REPR);
179 if (lookup->dest[1] != MP_OBJ_NULL) {
180 // Don't try to repr() lookup->dest[1], as we can be called recursively
181 DEBUG_printf(" <%s @%p>", mp_obj_get_type_str(lookup->dest[1]), MP_OBJ_TO_PTR(lookup->dest[1]));
182 }
183 DEBUG_printf("\n");
184 #endif
185 return;
186 }
187 }
188
189 // Previous code block takes care about attributes defined in .locals_dict,
190 // but some attributes of native types may be handled using .load_attr method,
191 // so make sure we try to lookup those too.
192 if (lookup->obj != NULL && !lookup->is_type && mp_obj_is_native_type(type) && type != &mp_type_object /* object is not a real type */) {
193 mp_load_method_maybe(lookup->obj->subobj[0], lookup->attr, lookup->dest);
194 if (lookup->dest[0] != MP_OBJ_NULL) {
195 return;
196 }
197 }
198
199 // attribute not found, keep searching base classes
200
201 if (type->parent == NULL) {
202 DEBUG_printf("mp_obj_class_lookup: No more parents\n");
203 return;
204 #if MICROPY_MULTIPLE_INHERITANCE
205 } else if (((mp_obj_base_t *)type->parent)->type == &mp_type_tuple) {
206 const mp_obj_tuple_t *parent_tuple = type->parent;
207 const mp_obj_t *item = parent_tuple->items;
208 const mp_obj_t *top = item + parent_tuple->len - 1;
209 for (; item < top; ++item) {
210 assert(mp_obj_is_type(*item, &mp_type_type));
211 mp_obj_type_t *bt = (mp_obj_type_t *)MP_OBJ_TO_PTR(*item);
212 if (bt == &mp_type_object) {
213 // Not a "real" type
214 continue;
215 }
216 mp_obj_class_lookup(lookup, bt);
217 if (lookup->dest[0] != MP_OBJ_NULL) {
218 return;
219 }
220 }
221
222 // search last base (simple tail recursion elimination)
223 assert(mp_obj_is_type(*item, &mp_type_type));
224 type = (mp_obj_type_t *)MP_OBJ_TO_PTR(*item);
225 #endif
226 } else {
227 type = type->parent;
228 }
229 if (type == &mp_type_object) {
230 // Not a "real" type
231 return;
232 }
233 }
234}
235
236STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
237 mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
238 qstr meth = (kind == PRINT_STR) ? MP_QSTR___str__ : MP_QSTR___repr__;
239 mp_obj_t member[2] = {MP_OBJ_NULL};
240 struct class_lookup_data lookup = {
241 .obj = self,
242 .attr = meth,
243 .meth_offset = offsetof(mp_obj_type_t, print),
244 .dest = member,
245 .is_type = false,
246 };
247 mp_obj_class_lookup(&lookup, self->base.type);
248 if (member[0] == MP_OBJ_NULL && kind == PRINT_STR) {
249 // If there's no __str__, fall back to __repr__
250 lookup.attr = MP_QSTR___repr__;
251 lookup.meth_offset = 0;
252 mp_obj_class_lookup(&lookup, self->base.type);
253 }
254
255 if (member[0] == MP_OBJ_SENTINEL) {
256 // Handle Exception subclasses specially
257 if (mp_obj_is_native_exception_instance(self->subobj[0])) {
258 if (kind != PRINT_STR) {
259 mp_print_str(print, qstr_str(self->base.type->name));
260 }
261 mp_obj_print_helper(print, self->subobj[0], kind | PRINT_EXC_SUBCLASS);
262 } else {
263 mp_obj_print_helper(print, self->subobj[0], kind);
264 }
265 return;
266 }
267
268 if (member[0] != MP_OBJ_NULL) {
269 mp_obj_t r = mp_call_function_1(member[0], self_in);
270 mp_obj_print_helper(print, r, PRINT_STR);
271 return;
272 }
273
274 // TODO: CPython prints fully-qualified type name
275 mp_printf(print, "<%s object at %p>", mp_obj_get_type_str(self_in), self);
276}
277
278mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) {
279 assert(mp_obj_is_instance_type(self));
280
281 // look for __new__ function
282 mp_obj_t init_fn[2] = {MP_OBJ_NULL};
283 struct class_lookup_data lookup = {
284 .obj = NULL,
285 .attr = MP_QSTR___new__,
286 .meth_offset = offsetof(mp_obj_type_t, make_new),
287 .dest = init_fn,
288 .is_type = false,
289 };
290 mp_obj_class_lookup(&lookup, self);
291
292 const mp_obj_type_t *native_base = NULL;
293 mp_obj_instance_t *o;
294 if (init_fn[0] == MP_OBJ_NULL || init_fn[0] == MP_OBJ_SENTINEL) {
295 // Either there is no __new__() method defined or there is a native
296 // constructor. In both cases create a blank instance.
297 o = mp_obj_new_instance(self, &native_base);
298
299 // Since type->make_new() implements both __new__() and __init__() in
300 // one go, of which the latter may be overridden by the Python subclass,
301 // we defer (see the end of this function) the call of the native
302 // constructor to give a chance for the Python __init__() method to call
303 // said native constructor.
304
305 } else {
306 // Call Python class __new__ function with all args to create an instance
307 mp_obj_t new_ret;
308 if (n_args == 0 && n_kw == 0) {
309 mp_obj_t args2[1] = {MP_OBJ_FROM_PTR(self)};
310 new_ret = mp_call_function_n_kw(init_fn[0], 1, 0, args2);
311 } else {
312 mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_args + 2 * n_kw);
313 args2[0] = MP_OBJ_FROM_PTR(self);
314 memcpy(args2 + 1, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t));
315 new_ret = mp_call_function_n_kw(init_fn[0], n_args + 1, n_kw, args2);
316 m_del(mp_obj_t, args2, 1 + n_args + 2 * n_kw);
317 }
318
319 // https://docs.python.org/3.4/reference/datamodel.html#object.__new__
320 // "If __new__() does not return an instance of cls, then the new
321 // instance's __init__() method will not be invoked."
322 if (mp_obj_get_type(new_ret) != self) {
323 return new_ret;
324 }
325
326 // The instance returned by __new__() becomes the new object
327 o = MP_OBJ_TO_PTR(new_ret);
328 }
329
330 // now call Python class __init__ function with all args
331 // This method has a chance to call super().__init__() to construct a
332 // possible native base class.
333 init_fn[0] = init_fn[1] = MP_OBJ_NULL;
334 lookup.obj = o;
335 lookup.attr = MP_QSTR___init__;
336 lookup.meth_offset = 0;
337 mp_obj_class_lookup(&lookup, self);
338 if (init_fn[0] != MP_OBJ_NULL) {
339 mp_obj_t init_ret;
340 if (n_args == 0 && n_kw == 0) {
341 init_ret = mp_call_method_n_kw(0, 0, init_fn);
342 } else {
343 mp_obj_t *args2 = m_new(mp_obj_t, 2 + n_args + 2 * n_kw);
344 args2[0] = init_fn[0];
345 args2[1] = init_fn[1];
346 memcpy(args2 + 2, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t));
347 init_ret = mp_call_method_n_kw(n_args, n_kw, args2);
348 m_del(mp_obj_t, args2, 2 + n_args + 2 * n_kw);
349 }
350 if (init_ret != mp_const_none) {
351 #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE
352 mp_raise_TypeError(MP_ERROR_TEXT("__init__() should return None"));
353 #else
354 mp_raise_msg_varg(&mp_type_TypeError,
355 MP_ERROR_TEXT("__init__() should return None, not '%s'"), mp_obj_get_type_str(init_ret));
356 #endif
357 }
358 }
359
360 // If the type had a native base that was not explicitly initialised
361 // (constructed) by the Python __init__() method then construct it now.
362 if (native_base != NULL && o->subobj[0] == MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj)) {
363 o->subobj[0] = native_base->make_new(native_base, n_args, n_kw, args);
364 }
365
366 return MP_OBJ_FROM_PTR(o);
367}
368
369// Qstrs for special methods are guaranteed to have a small value, so we use byte
370// type to represent them.
371const byte mp_unary_op_method_name[MP_UNARY_OP_NUM_RUNTIME] = {
372 [MP_UNARY_OP_BOOL] = MP_QSTR___bool__,
373 [MP_UNARY_OP_LEN] = MP_QSTR___len__,
374 [MP_UNARY_OP_HASH] = MP_QSTR___hash__,
375 [MP_UNARY_OP_INT] = MP_QSTR___int__,
376 #if MICROPY_PY_ALL_SPECIAL_METHODS
377 [MP_UNARY_OP_POSITIVE] = MP_QSTR___pos__,
378 [MP_UNARY_OP_NEGATIVE] = MP_QSTR___neg__,
379 [MP_UNARY_OP_INVERT] = MP_QSTR___invert__,
380 [MP_UNARY_OP_ABS] = MP_QSTR___abs__,
381 #endif
382 #if MICROPY_PY_SYS_GETSIZEOF
383 [MP_UNARY_OP_SIZEOF] = MP_QSTR___sizeof__,
384 #endif
385};
386
387STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
388 mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
389
390 #if MICROPY_PY_SYS_GETSIZEOF
391 if (MP_UNLIKELY(op == MP_UNARY_OP_SIZEOF)) {
392 // TODO: This doesn't count inherited objects (self->subobj)
393 const mp_obj_type_t *native_base;
394 size_t num_native_bases = instance_count_native_bases(mp_obj_get_type(self_in), &native_base);
395
396 size_t sz = sizeof(*self) + sizeof(*self->subobj) * num_native_bases
397 + sizeof(*self->members.table) * self->members.alloc;
398 return MP_OBJ_NEW_SMALL_INT(sz);
399 }
400 #endif
401
402 qstr op_name = mp_unary_op_method_name[op];
403 /* Still try to lookup native slot
404 if (op_name == 0) {
405 return MP_OBJ_NULL;
406 }
407 */
408 mp_obj_t member[2] = {MP_OBJ_NULL};
409 struct class_lookup_data lookup = {
410 .obj = self,
411 .attr = op_name,
412 .meth_offset = offsetof(mp_obj_type_t, unary_op),
413 .dest = member,
414 .is_type = false,
415 };
416 mp_obj_class_lookup(&lookup, self->base.type);
417 if (member[0] == MP_OBJ_SENTINEL) {
418 return mp_unary_op(op, self->subobj[0]);
419 } else if (member[0] != MP_OBJ_NULL) {
420 mp_obj_t val = mp_call_function_1(member[0], self_in);
421
422 switch (op) {
423 case MP_UNARY_OP_HASH:
424 // __hash__ must return a small int
425 val = MP_OBJ_NEW_SMALL_INT(mp_obj_get_int_truncated(val));
426 break;
427 case MP_UNARY_OP_INT:
428 // Must return int
429 if (!mp_obj_is_int(val)) {
430 mp_raise_TypeError(NULL);
431 }
432 break;
433 default:
434 // No need to do anything
435 ;
436 }
437 return val;
438 } else {
439 if (op == MP_UNARY_OP_HASH) {
440 lookup.attr = MP_QSTR___eq__;
441 mp_obj_class_lookup(&lookup, self->base.type);
442 if (member[0] == MP_OBJ_NULL) {
443 // https://docs.python.org/3/reference/datamodel.html#object.__hash__
444 // "User-defined classes have __eq__() and __hash__() methods by default;
445 // with them, all objects compare unequal (except with themselves) and
446 // x.__hash__() returns an appropriate value such that x == y implies
447 // both that x is y and hash(x) == hash(y)."
448 return MP_OBJ_NEW_SMALL_INT((mp_uint_t)self_in);
449 }
450 // "A class that overrides __eq__() and does not define __hash__() will have its __hash__() implicitly set to None.
451 // When the __hash__() method of a class is None, instances of the class will raise an appropriate TypeError"
452 }
453
454 return MP_OBJ_NULL; // op not supported
455 }
456}
457
458// Binary-op enum values not listed here will have the default value of 0 in the
459// table, corresponding to MP_QSTRnull, and are therefore unsupported (a lookup will
460// fail). They can be added at the expense of code size for the qstr.
461// Qstrs for special methods are guaranteed to have a small value, so we use byte
462// type to represent them.
463const byte mp_binary_op_method_name[MP_BINARY_OP_NUM_RUNTIME] = {
464 [MP_BINARY_OP_LESS] = MP_QSTR___lt__,
465 [MP_BINARY_OP_MORE] = MP_QSTR___gt__,
466 [MP_BINARY_OP_EQUAL] = MP_QSTR___eq__,
467 [MP_BINARY_OP_LESS_EQUAL] = MP_QSTR___le__,
468 [MP_BINARY_OP_MORE_EQUAL] = MP_QSTR___ge__,
469 [MP_BINARY_OP_NOT_EQUAL] = MP_QSTR___ne__,
470 [MP_BINARY_OP_CONTAINS] = MP_QSTR___contains__,
471
472 // If an inplace method is not found a normal method will be used as a fallback
473 [MP_BINARY_OP_INPLACE_ADD] = MP_QSTR___iadd__,
474 [MP_BINARY_OP_INPLACE_SUBTRACT] = MP_QSTR___isub__,
475 #if MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS
476 [MP_BINARY_OP_INPLACE_MULTIPLY] = MP_QSTR___imul__,
477 [MP_BINARY_OP_INPLACE_MAT_MULTIPLY] = MP_QSTR___imatmul__,
478 [MP_BINARY_OP_INPLACE_FLOOR_DIVIDE] = MP_QSTR___ifloordiv__,
479 [MP_BINARY_OP_INPLACE_TRUE_DIVIDE] = MP_QSTR___itruediv__,
480 [MP_BINARY_OP_INPLACE_MODULO] = MP_QSTR___imod__,
481 [MP_BINARY_OP_INPLACE_POWER] = MP_QSTR___ipow__,
482 [MP_BINARY_OP_INPLACE_OR] = MP_QSTR___ior__,
483 [MP_BINARY_OP_INPLACE_XOR] = MP_QSTR___ixor__,
484 [MP_BINARY_OP_INPLACE_AND] = MP_QSTR___iand__,
485 [MP_BINARY_OP_INPLACE_LSHIFT] = MP_QSTR___ilshift__,
486 [MP_BINARY_OP_INPLACE_RSHIFT] = MP_QSTR___irshift__,
487 #endif
488
489 [MP_BINARY_OP_ADD] = MP_QSTR___add__,
490 [MP_BINARY_OP_SUBTRACT] = MP_QSTR___sub__,
491 #if MICROPY_PY_ALL_SPECIAL_METHODS
492 [MP_BINARY_OP_MULTIPLY] = MP_QSTR___mul__,
493 [MP_BINARY_OP_MAT_MULTIPLY] = MP_QSTR___matmul__,
494 [MP_BINARY_OP_FLOOR_DIVIDE] = MP_QSTR___floordiv__,
495 [MP_BINARY_OP_TRUE_DIVIDE] = MP_QSTR___truediv__,
496 [MP_BINARY_OP_MODULO] = MP_QSTR___mod__,
497 [MP_BINARY_OP_DIVMOD] = MP_QSTR___divmod__,
498 [MP_BINARY_OP_POWER] = MP_QSTR___pow__,
499 [MP_BINARY_OP_OR] = MP_QSTR___or__,
500 [MP_BINARY_OP_XOR] = MP_QSTR___xor__,
501 [MP_BINARY_OP_AND] = MP_QSTR___and__,
502 [MP_BINARY_OP_LSHIFT] = MP_QSTR___lshift__,
503 [MP_BINARY_OP_RSHIFT] = MP_QSTR___rshift__,
504 #endif
505
506 #if MICROPY_PY_REVERSE_SPECIAL_METHODS
507 [MP_BINARY_OP_REVERSE_ADD] = MP_QSTR___radd__,
508 [MP_BINARY_OP_REVERSE_SUBTRACT] = MP_QSTR___rsub__,
509 #if MICROPY_PY_ALL_SPECIAL_METHODS
510 [MP_BINARY_OP_REVERSE_MULTIPLY] = MP_QSTR___rmul__,
511 [MP_BINARY_OP_REVERSE_MAT_MULTIPLY] = MP_QSTR___rmatmul__,
512 [MP_BINARY_OP_REVERSE_FLOOR_DIVIDE] = MP_QSTR___rfloordiv__,
513 [MP_BINARY_OP_REVERSE_TRUE_DIVIDE] = MP_QSTR___rtruediv__,
514 [MP_BINARY_OP_REVERSE_MODULO] = MP_QSTR___rmod__,
515 [MP_BINARY_OP_REVERSE_POWER] = MP_QSTR___rpow__,
516 [MP_BINARY_OP_REVERSE_OR] = MP_QSTR___ror__,
517 [MP_BINARY_OP_REVERSE_XOR] = MP_QSTR___rxor__,
518 [MP_BINARY_OP_REVERSE_AND] = MP_QSTR___rand__,
519 [MP_BINARY_OP_REVERSE_LSHIFT] = MP_QSTR___rlshift__,
520 [MP_BINARY_OP_REVERSE_RSHIFT] = MP_QSTR___rrshift__,
521 #endif
522 #endif
523};
524
525STATIC mp_obj_t instance_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
526 // Note: For ducktyping, CPython does not look in the instance members or use
527 // __getattr__ or __getattribute__. It only looks in the class dictionary.
528 mp_obj_instance_t *lhs = MP_OBJ_TO_PTR(lhs_in);
529retry:;
530 qstr op_name = mp_binary_op_method_name[op];
531 /* Still try to lookup native slot
532 if (op_name == 0) {
533 return MP_OBJ_NULL;
534 }
535 */
536 mp_obj_t dest[3] = {MP_OBJ_NULL};
537 struct class_lookup_data lookup = {
538 .obj = lhs,
539 .attr = op_name,
540 .meth_offset = offsetof(mp_obj_type_t, binary_op),
541 .dest = dest,
542 .is_type = false,
543 };
544 mp_obj_class_lookup(&lookup, lhs->base.type);
545
546 mp_obj_t res;
547 if (dest[0] == MP_OBJ_SENTINEL) {
548 res = mp_binary_op(op, lhs->subobj[0], rhs_in);
549 } else if (dest[0] != MP_OBJ_NULL) {
550 dest[2] = rhs_in;
551 res = mp_call_method_n_kw(1, 0, dest);
552 } else {
553 // If this was an inplace method, fallback to normal method
554 // https://docs.python.org/3/reference/datamodel.html#object.__iadd__ :
555 // "If a specific method is not defined, the augmented assignment
556 // falls back to the normal methods."
557 if (op >= MP_BINARY_OP_INPLACE_OR && op <= MP_BINARY_OP_INPLACE_POWER) {
558 op -= MP_BINARY_OP_INPLACE_OR - MP_BINARY_OP_OR;
559 goto retry;
560 }
561 return MP_OBJ_NULL; // op not supported
562 }
563
564 #if MICROPY_PY_BUILTINS_NOTIMPLEMENTED
565 // NotImplemented means "try other fallbacks (like calling __rop__
566 // instead of __op__) and if nothing works, raise TypeError". As
567 // MicroPython doesn't implement any fallbacks, signal to raise
568 // TypeError right away.
569 if (res == mp_const_notimplemented) {
570 return MP_OBJ_NULL; // op not supported
571 }
572 #endif
573
574 return res;
575}
576
577STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
578 // logic: look in instance members then class locals
579 assert(mp_obj_is_instance_type(mp_obj_get_type(self_in)));
580 mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
581
582 mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
583 if (elem != NULL) {
584 // object member, always treated as a value
585 dest[0] = elem->value;
586 return;
587 }
588 #if MICROPY_CPYTHON_COMPAT
589 if (attr == MP_QSTR___dict__) {
590 // Create a new dict with a copy of the instance's map items.
591 // This creates, unlike CPython, a read-only __dict__ that can't be modified.
592 mp_obj_dict_t dict;
593 dict.base.type = &mp_type_dict;
594 dict.map = self->members;
595 dest[0] = mp_obj_dict_copy(MP_OBJ_FROM_PTR(&dict));
596 mp_obj_dict_t *dest_dict = MP_OBJ_TO_PTR(dest[0]);
597 dest_dict->map.is_fixed = 1;
598 return;
599 }
600 #endif
601 struct class_lookup_data lookup = {
602 .obj = self,
603 .attr = attr,
604 .meth_offset = 0,
605 .dest = dest,
606 .is_type = false,
607 };
608 mp_obj_class_lookup(&lookup, self->base.type);
609 mp_obj_t member = dest[0];
610 if (member != MP_OBJ_NULL) {
611 if (!(self->base.type->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) {
612 // Class doesn't have any special accessors to check so return straightaway
613 return;
614 }
615
616 #if MICROPY_PY_BUILTINS_PROPERTY
617 if (mp_obj_is_type(member, &mp_type_property)) {
618 // object member is a property; delegate the load to the property
619 // Note: This is an optimisation for code size and execution time.
620 // The proper way to do it is have the functionality just below
621 // in a __get__ method of the property object, and then it would
622 // be called by the descriptor code down below. But that way
623 // requires overhead for the nested mp_call's and overhead for
624 // the code.
625 const mp_obj_t *proxy = mp_obj_property_get(member);
626 if (proxy[0] == mp_const_none) {
627 mp_raise_msg(&mp_type_AttributeError, MP_ERROR_TEXT("unreadable attribute"));
628 } else {
629 dest[0] = mp_call_function_n_kw(proxy[0], 1, 0, &self_in);
630 }
631 return;
632 }
633 #endif
634
635 #if MICROPY_PY_DESCRIPTORS
636 // found a class attribute; if it has a __get__ method then call it with the
637 // class instance and class as arguments and return the result
638 // Note that this is functionally correct but very slow: each load_attr
639 // requires an extra mp_load_method_maybe to check for the __get__.
640 mp_obj_t attr_get_method[4];
641 mp_load_method_maybe(member, MP_QSTR___get__, attr_get_method);
642 if (attr_get_method[0] != MP_OBJ_NULL) {
643 attr_get_method[2] = self_in;
644 attr_get_method[3] = MP_OBJ_FROM_PTR(mp_obj_get_type(self_in));
645 dest[0] = mp_call_method_n_kw(2, 0, attr_get_method);
646 }
647 #endif
648 return;
649 }
650
651 // try __getattr__
652 if (attr != MP_QSTR___getattr__) {
653 #if MICROPY_PY_DELATTR_SETATTR
654 // If the requested attr is __setattr__/__delattr__ then don't delegate the lookup
655 // to __getattr__. If we followed CPython's behaviour then __setattr__/__delattr__
656 // would have already been found in the "object" base class.
657 if (attr == MP_QSTR___setattr__ || attr == MP_QSTR___delattr__) {
658 return;
659 }
660 #endif
661
662 mp_obj_t dest2[3];
663 mp_load_method_maybe(self_in, MP_QSTR___getattr__, dest2);
664 if (dest2[0] != MP_OBJ_NULL) {
665 // __getattr__ exists, call it and return its result
666 dest2[2] = MP_OBJ_NEW_QSTR(attr);
667 dest[0] = mp_call_method_n_kw(1, 0, dest2);
668 return;
669 }
670 }
671}
672
673STATIC bool mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
674 mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
675
676 if (!(self->base.type->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) {
677 // Class doesn't have any special accessors so skip their checks
678 goto skip_special_accessors;
679 }
680
681 #if MICROPY_PY_BUILTINS_PROPERTY || MICROPY_PY_DESCRIPTORS
682 // With property and/or descriptors enabled we need to do a lookup
683 // first in the class dict for the attribute to see if the store should
684 // be delegated.
685 mp_obj_t member[2] = {MP_OBJ_NULL};
686 struct class_lookup_data lookup = {
687 .obj = self,
688 .attr = attr,
689 .meth_offset = 0,
690 .dest = member,
691 .is_type = false,
692 };
693 mp_obj_class_lookup(&lookup, self->base.type);
694
695 if (member[0] != MP_OBJ_NULL) {
696 #if MICROPY_PY_BUILTINS_PROPERTY
697 if (mp_obj_is_type(member[0], &mp_type_property)) {
698 // attribute exists and is a property; delegate the store/delete
699 // Note: This is an optimisation for code size and execution time.
700 // The proper way to do it is have the functionality just below in
701 // a __set__/__delete__ method of the property object, and then it
702 // would be called by the descriptor code down below. But that way
703 // requires overhead for the nested mp_call's and overhead for
704 // the code.
705 const mp_obj_t *proxy = mp_obj_property_get(member[0]);
706 mp_obj_t dest[2] = {self_in, value};
707 if (value == MP_OBJ_NULL) {
708 // delete attribute
709 if (proxy[2] == mp_const_none) {
710 // TODO better error message?
711 return false;
712 } else {
713 mp_call_function_n_kw(proxy[2], 1, 0, dest);
714 return true;
715 }
716 } else {
717 // store attribute
718 if (proxy[1] == mp_const_none) {
719 // TODO better error message?
720 return false;
721 } else {
722 mp_call_function_n_kw(proxy[1], 2, 0, dest);
723 return true;
724 }
725 }
726 }
727 #endif
728
729 #if MICROPY_PY_DESCRIPTORS
730 // found a class attribute; if it has a __set__/__delete__ method then
731 // call it with the class instance (and value) as arguments
732 if (value == MP_OBJ_NULL) {
733 // delete attribute
734 mp_obj_t attr_delete_method[3];
735 mp_load_method_maybe(member[0], MP_QSTR___delete__, attr_delete_method);
736 if (attr_delete_method[0] != MP_OBJ_NULL) {
737 attr_delete_method[2] = self_in;
738 mp_call_method_n_kw(1, 0, attr_delete_method);
739 return true;
740 }
741 } else {
742 // store attribute
743 mp_obj_t attr_set_method[4];
744 mp_load_method_maybe(member[0], MP_QSTR___set__, attr_set_method);
745 if (attr_set_method[0] != MP_OBJ_NULL) {
746 attr_set_method[2] = self_in;
747 attr_set_method[3] = value;
748 mp_call_method_n_kw(2, 0, attr_set_method);
749 return true;
750 }
751 }
752 #endif
753 }
754 #endif
755
756 #if MICROPY_PY_DELATTR_SETATTR
757 if (value == MP_OBJ_NULL) {
758 // delete attribute
759 // try __delattr__ first
760 mp_obj_t attr_delattr_method[3];
761 mp_load_method_maybe(self_in, MP_QSTR___delattr__, attr_delattr_method);
762 if (attr_delattr_method[0] != MP_OBJ_NULL) {
763 // __delattr__ exists, so call it
764 attr_delattr_method[2] = MP_OBJ_NEW_QSTR(attr);
765 mp_call_method_n_kw(1, 0, attr_delattr_method);
766 return true;
767 }
768 } else {
769 // store attribute
770 // try __setattr__ first
771 mp_obj_t attr_setattr_method[4];
772 mp_load_method_maybe(self_in, MP_QSTR___setattr__, attr_setattr_method);
773 if (attr_setattr_method[0] != MP_OBJ_NULL) {
774 // __setattr__ exists, so call it
775 attr_setattr_method[2] = MP_OBJ_NEW_QSTR(attr);
776 attr_setattr_method[3] = value;
777 mp_call_method_n_kw(2, 0, attr_setattr_method);
778 return true;
779 }
780 }
781 #endif
782
783skip_special_accessors:
784
785 if (value == MP_OBJ_NULL) {
786 // delete attribute
787 mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
788 return elem != NULL;
789 } else {
790 // store attribute
791 mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
792 return true;
793 }
794}
795
796STATIC void mp_obj_instance_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
797 if (dest[0] == MP_OBJ_NULL) {
798 mp_obj_instance_load_attr(self_in, attr, dest);
799 } else {
800 if (mp_obj_instance_store_attr(self_in, attr, dest[1])) {
801 dest[0] = MP_OBJ_NULL; // indicate success
802 }
803 }
804}
805
806STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
807 mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
808 mp_obj_t member[4] = {MP_OBJ_NULL, MP_OBJ_NULL, index, value};
809 struct class_lookup_data lookup = {
810 .obj = self,
811 .meth_offset = offsetof(mp_obj_type_t, subscr),
812 .dest = member,
813 .is_type = false,
814 };
815 if (value == MP_OBJ_NULL) {
816 // delete item
817 lookup.attr = MP_QSTR___delitem__;
818 } else if (value == MP_OBJ_SENTINEL) {
819 // load item
820 lookup.attr = MP_QSTR___getitem__;
821 } else {
822 // store item
823 lookup.attr = MP_QSTR___setitem__;
824 }
825 mp_obj_class_lookup(&lookup, self->base.type);
826 if (member[0] == MP_OBJ_SENTINEL) {
827 return mp_obj_subscr(self->subobj[0], index, value);
828 } else if (member[0] != MP_OBJ_NULL) {
829 size_t n_args = value == MP_OBJ_NULL || value == MP_OBJ_SENTINEL ? 1 : 2;
830 mp_obj_t ret = mp_call_method_n_kw(n_args, 0, member);
831 if (value == MP_OBJ_SENTINEL) {
832 return ret;
833 } else {
834 return mp_const_none;
835 }
836 } else {
837 return MP_OBJ_NULL; // op not supported
838 }
839}
840
841STATIC mp_obj_t mp_obj_instance_get_call(mp_obj_t self_in, mp_obj_t *member) {
842 mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
843 struct class_lookup_data lookup = {
844 .obj = self,
845 .attr = MP_QSTR___call__,
846 .meth_offset = offsetof(mp_obj_type_t, call),
847 .dest = member,
848 .is_type = false,
849 };
850 mp_obj_class_lookup(&lookup, self->base.type);
851 return member[0];
852}
853
854bool mp_obj_instance_is_callable(mp_obj_t self_in) {
855 mp_obj_t member[2] = {MP_OBJ_NULL, MP_OBJ_NULL};
856 return mp_obj_instance_get_call(self_in, member) != MP_OBJ_NULL;
857}
858
859mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
860 mp_obj_t member[2] = {MP_OBJ_NULL, MP_OBJ_NULL};
861 mp_obj_t call = mp_obj_instance_get_call(self_in, member);
862 if (call == MP_OBJ_NULL) {
863 #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE
864 mp_raise_TypeError(MP_ERROR_TEXT("object not callable"));
865 #else
866 mp_raise_msg_varg(&mp_type_TypeError,
867 MP_ERROR_TEXT("'%s' object isn't callable"), mp_obj_get_type_str(self_in));
868 #endif
869 }
870 mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
871 if (call == MP_OBJ_SENTINEL) {
872 return mp_call_function_n_kw(self->subobj[0], n_args, n_kw, args);
873 }
874
875 return mp_call_method_self_n_kw(member[0], member[1], n_args, n_kw, args);
876}
877
878// Note that iter_buf may be NULL, and needs to be allocated if needed
879mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
880 mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
881 mp_obj_t member[2] = {MP_OBJ_NULL};
882 struct class_lookup_data lookup = {
883 .obj = self,
884 .attr = MP_QSTR___iter__,
885 .meth_offset = offsetof(mp_obj_type_t, getiter),
886 .dest = member,
887 .is_type = false,
888 };
889 mp_obj_class_lookup(&lookup, self->base.type);
890 if (member[0] == MP_OBJ_NULL) {
891 return MP_OBJ_NULL;
892 } else if (member[0] == MP_OBJ_SENTINEL) {
893 const mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]);
894 if (iter_buf == NULL) {
895 iter_buf = m_new_obj(mp_obj_iter_buf_t);
896 }
897 return type->getiter(self->subobj[0], iter_buf);
898 } else {
899 return mp_call_method_n_kw(0, 0, member);
900 }
901}
902
903STATIC mp_int_t instance_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
904 mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
905 mp_obj_t member[2] = {MP_OBJ_NULL};
906 struct class_lookup_data lookup = {
907 .obj = self,
908 .attr = MP_QSTR_, // don't actually look for a method
909 .meth_offset = offsetof(mp_obj_type_t, buffer_p.get_buffer),
910 .dest = member,
911 .is_type = false,
912 };
913 mp_obj_class_lookup(&lookup, self->base.type);
914 if (member[0] == MP_OBJ_SENTINEL) {
915 const mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]);
916 return type->buffer_p.get_buffer(self->subobj[0], bufinfo, flags);
917 } else {
918 return 1; // object does not support buffer protocol
919 }
920}
921
922/******************************************************************************/
923// type object
924// - the struct is mp_obj_type_t and is defined in obj.h so const types can be made
925// - there is a constant mp_obj_type_t (called mp_type_type) for the 'type' object
926// - creating a new class (a new type) creates a new mp_obj_type_t
927
928#if ENABLE_SPECIAL_ACCESSORS
929STATIC bool check_for_special_accessors(mp_obj_t key, mp_obj_t value) {
930 #if MICROPY_PY_DELATTR_SETATTR
931 if (key == MP_OBJ_NEW_QSTR(MP_QSTR___setattr__) || key == MP_OBJ_NEW_QSTR(MP_QSTR___delattr__)) {
932 return true;
933 }
934 #endif
935 #if MICROPY_PY_BUILTINS_PROPERTY
936 if (mp_obj_is_type(value, &mp_type_property)) {
937 return true;
938 }
939 #endif
940 #if MICROPY_PY_DESCRIPTORS
941 static const uint8_t to_check[] = {
942 MP_QSTR___get__, MP_QSTR___set__, MP_QSTR___delete__,
943 };
944 for (size_t i = 0; i < MP_ARRAY_SIZE(to_check); ++i) {
945 mp_obj_t dest_temp[2];
946 mp_load_method_protected(value, to_check[i], dest_temp, true);
947 if (dest_temp[0] != MP_OBJ_NULL) {
948 return true;
949 }
950 }
951 #endif
952 return false;
953}
954#endif
955
956STATIC void type_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
957 (void)kind;
958 mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in);
959 mp_printf(print, "<class '%q'>", self->name);
960}
961
962STATIC mp_obj_t type_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
963 (void)type_in;
964
965 mp_arg_check_num(n_args, n_kw, 1, 3, false);
966
967 switch (n_args) {
968 case 1:
969 return MP_OBJ_FROM_PTR(mp_obj_get_type(args[0]));
970
971 case 3:
972 // args[0] = name
973 // args[1] = bases tuple
974 // args[2] = locals dict
975 return mp_obj_new_type(mp_obj_str_get_qstr(args[0]), args[1], args[2]);
976
977 default:
978 mp_raise_TypeError(MP_ERROR_TEXT("type takes 1 or 3 arguments"));
979 }
980}
981
982STATIC mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
983 // instantiate an instance of a class
984
985 mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in);
986
987 if (self->make_new == NULL) {
988 #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE
989 mp_raise_TypeError(MP_ERROR_TEXT("can't create instance"));
990 #else
991 mp_raise_msg_varg(&mp_type_TypeError, MP_ERROR_TEXT("can't create '%q' instances"), self->name);
992 #endif
993 }
994
995 // make new instance
996 mp_obj_t o = self->make_new(self, n_args, n_kw, args);
997
998 // return new instance
999 return o;
1000}
1001
1002STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
1003 assert(mp_obj_is_type(self_in, &mp_type_type));
1004 mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in);
1005
1006 if (dest[0] == MP_OBJ_NULL) {
1007 // load attribute
1008 #if MICROPY_CPYTHON_COMPAT
1009 if (attr == MP_QSTR___name__) {
1010 dest[0] = MP_OBJ_NEW_QSTR(self->name);
1011 return;
1012 }
1013 #if MICROPY_CPYTHON_COMPAT
1014 if (attr == MP_QSTR___dict__) {
1015 // Returns a read-only dict of the class attributes.
1016 // If the internal locals is not fixed, a copy will be created.
1017 const mp_obj_dict_t *dict = self->locals_dict;
1018 if (!dict) {
1019 dict = &mp_const_empty_dict_obj;
1020 }
1021 if (dict->map.is_fixed) {
1022 dest[0] = MP_OBJ_FROM_PTR(dict);
1023 } else {
1024 dest[0] = mp_obj_dict_copy(MP_OBJ_FROM_PTR(dict));
1025 mp_obj_dict_t *dict_copy = MP_OBJ_TO_PTR(dest[0]);
1026 dict_copy->map.is_fixed = 1;
1027 }
1028 return;
1029 }
1030 #endif
1031 if (attr == MP_QSTR___bases__) {
1032 if (self == &mp_type_object) {
1033 dest[0] = mp_const_empty_tuple;
1034 return;
1035 }
1036 mp_obj_t parent_obj = self->parent ? MP_OBJ_FROM_PTR(self->parent) : MP_OBJ_FROM_PTR(&mp_type_object);
1037 #if MICROPY_MULTIPLE_INHERITANCE
1038 if (mp_obj_is_type(parent_obj, &mp_type_tuple)) {
1039 dest[0] = parent_obj;
1040 return;
1041 }
1042 #endif
1043 dest[0] = mp_obj_new_tuple(1, &parent_obj);
1044 return;
1045 }
1046 #endif
1047 struct class_lookup_data lookup = {
1048 .obj = (mp_obj_instance_t *)self,
1049 .attr = attr,
1050 .meth_offset = 0,
1051 .dest = dest,
1052 .is_type = true,
1053 };
1054 mp_obj_class_lookup(&lookup, self);
1055 } else {
1056 // delete/store attribute
1057
1058 if (self->locals_dict != NULL) {
1059 assert(mp_obj_is_dict_or_ordereddict(MP_OBJ_FROM_PTR(self->locals_dict))); // MicroPython restriction, for now
1060 mp_map_t *locals_map = &self->locals_dict->map;
1061 if (locals_map->is_fixed) {
1062 // can't apply delete/store to a fixed map
1063 return;
1064 }
1065 if (dest[1] == MP_OBJ_NULL) {
1066 // delete attribute
1067 mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
1068 if (elem != NULL) {
1069 dest[0] = MP_OBJ_NULL; // indicate success
1070 }
1071 } else {
1072 #if ENABLE_SPECIAL_ACCESSORS
1073 // Check if we add any special accessor methods with this store
1074 if (!(self->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) {
1075 if (check_for_special_accessors(MP_OBJ_NEW_QSTR(attr), dest[1])) {
1076 if (self->flags & MP_TYPE_FLAG_IS_SUBCLASSED) {
1077 // This class is already subclassed so can't have special accessors added
1078 mp_raise_msg(&mp_type_AttributeError, MP_ERROR_TEXT("can't add special method to already-subclassed class"));
1079 }
1080 self->flags |= MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS;
1081 }
1082 }
1083 #endif
1084
1085 // store attribute
1086 mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
1087 elem->value = dest[1];
1088 dest[0] = MP_OBJ_NULL; // indicate success
1089 }
1090 }
1091 }
1092}
1093
1094const mp_obj_type_t mp_type_type = {
1095 { &mp_type_type },
1096 .name = MP_QSTR_type,
1097 .print = type_print,
1098 .make_new = type_make_new,
1099 .call = type_call,
1100 .unary_op = mp_generic_unary_op,
1101 .attr = type_attr,
1102};
1103
1104mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) {
1105 // Verify input objects have expected type
1106 if (!mp_obj_is_type(bases_tuple, &mp_type_tuple)) {
1107 mp_raise_TypeError(NULL);
1108 }
1109 if (!mp_obj_is_dict_or_ordereddict(locals_dict)) {
1110 mp_raise_TypeError(NULL);
1111 }
1112
1113 // TODO might need to make a copy of locals_dict; at least that's how CPython does it
1114
1115 // Basic validation of base classes
1116 uint16_t base_flags = MP_TYPE_FLAG_EQ_NOT_REFLEXIVE
1117 | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EQ_HAS_NEQ_TEST;
1118 size_t bases_len;
1119 mp_obj_t *bases_items;
1120 mp_obj_tuple_get(bases_tuple, &bases_len, &bases_items);
1121 for (size_t i = 0; i < bases_len; i++) {
1122 if (!mp_obj_is_type(bases_items[i], &mp_type_type)) {
1123 mp_raise_TypeError(NULL);
1124 }
1125 mp_obj_type_t *t = MP_OBJ_TO_PTR(bases_items[i]);
1126 // TODO: Verify with CPy, tested on function type
1127 if (t->make_new == NULL) {
1128 #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE
1129 mp_raise_TypeError(MP_ERROR_TEXT("type isn't an acceptable base type"));
1130 #else
1131 mp_raise_msg_varg(&mp_type_TypeError,
1132 MP_ERROR_TEXT("type '%q' isn't an acceptable base type"), t->name);
1133 #endif
1134 }
1135 #if ENABLE_SPECIAL_ACCESSORS
1136 if (mp_obj_is_instance_type(t)) {
1137 t->flags |= MP_TYPE_FLAG_IS_SUBCLASSED;
1138 base_flags |= t->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS;
1139 }
1140 #endif
1141 }
1142
1143 mp_obj_type_t *o = m_new0(mp_obj_type_t, 1);
1144 o->base.type = &mp_type_type;
1145 o->flags = base_flags;
1146 o->name = name;
1147 o->print = instance_print;
1148 o->make_new = mp_obj_instance_make_new;
1149 o->call = mp_obj_instance_call;
1150 o->unary_op = instance_unary_op;
1151 o->binary_op = instance_binary_op;
1152 o->attr = mp_obj_instance_attr;
1153 o->subscr = instance_subscr;
1154 o->getiter = mp_obj_instance_getiter;
1155 // o->iternext = ; not implemented
1156 o->buffer_p.get_buffer = instance_get_buffer;
1157
1158 if (bases_len > 0) {
1159 // Inherit protocol from a base class. This allows to define an
1160 // abstract base class which would translate C-level protocol to
1161 // Python method calls, and any subclass inheriting from it will
1162 // support this feature.
1163 o->protocol = ((mp_obj_type_t *)MP_OBJ_TO_PTR(bases_items[0]))->protocol;
1164
1165 if (bases_len >= 2) {
1166 #if MICROPY_MULTIPLE_INHERITANCE
1167 o->parent = MP_OBJ_TO_PTR(bases_tuple);
1168 #else
1169 mp_raise_NotImplementedError(MP_ERROR_TEXT("multiple inheritance not supported"));
1170 #endif
1171 } else {
1172 o->parent = MP_OBJ_TO_PTR(bases_items[0]);
1173 }
1174 }
1175
1176 o->locals_dict = MP_OBJ_TO_PTR(locals_dict);
1177
1178 #if ENABLE_SPECIAL_ACCESSORS
1179 // Check if the class has any special accessor methods
1180 if (!(o->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) {
1181 for (size_t i = 0; i < o->locals_dict->map.alloc; i++) {
1182 if (mp_map_slot_is_filled(&o->locals_dict->map, i)) {
1183 const mp_map_elem_t *elem = &o->locals_dict->map.table[i];
1184 if (check_for_special_accessors(elem->key, elem->value)) {
1185 o->flags |= MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS;
1186 break;
1187 }
1188 }
1189 }
1190 }
1191 #endif
1192
1193 const mp_obj_type_t *native_base;
1194 size_t num_native_bases = instance_count_native_bases(o, &native_base);
1195 if (num_native_bases > 1) {
1196 mp_raise_TypeError(MP_ERROR_TEXT("multiple bases have instance lay-out conflict"));
1197 }
1198
1199 mp_map_t *locals_map = &o->locals_dict->map;
1200 mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP);
1201 if (elem != NULL) {
1202 // __new__ slot exists; check if it is a function
1203 if (mp_obj_is_fun(elem->value)) {
1204 // __new__ is a function, wrap it in a staticmethod decorator
1205 elem->value = static_class_method_make_new(&mp_type_staticmethod, 1, 0, &elem->value);
1206 }
1207 }
1208
1209 return MP_OBJ_FROM_PTR(o);
1210}
1211
1212/******************************************************************************/
1213// super object
1214
1215typedef struct _mp_obj_super_t {
1216 mp_obj_base_t base;
1217 mp_obj_t type;
1218 mp_obj_t obj;
1219} mp_obj_super_t;
1220
1221STATIC void super_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
1222 (void)kind;
1223 mp_obj_super_t *self = MP_OBJ_TO_PTR(self_in);
1224 mp_print_str(print, "<super: ");
1225 mp_obj_print_helper(print, self->type, PRINT_STR);
1226 mp_print_str(print, ", ");
1227 mp_obj_print_helper(print, self->obj, PRINT_STR);
1228 mp_print_str(print, ">");
1229}
1230
1231STATIC mp_obj_t super_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
1232 (void)type_in;
1233 // 0 arguments are turned into 2 in the compiler
1234 // 1 argument is not yet implemented
1235 mp_arg_check_num(n_args, n_kw, 2, 2, false);
1236 if (!mp_obj_is_type(args[0], &mp_type_type)) {
1237 mp_raise_TypeError(NULL);
1238 }
1239 mp_obj_super_t *o = m_new_obj(mp_obj_super_t);
1240 *o = (mp_obj_super_t) {{type_in}, args[0], args[1]};
1241 return MP_OBJ_FROM_PTR(o);
1242}
1243
1244STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
1245 if (dest[0] != MP_OBJ_NULL) {
1246 // not load attribute
1247 return;
1248 }
1249
1250 assert(mp_obj_is_type(self_in, &mp_type_super));
1251 mp_obj_super_t *self = MP_OBJ_TO_PTR(self_in);
1252
1253 assert(mp_obj_is_type(self->type, &mp_type_type));
1254
1255 mp_obj_type_t *type = MP_OBJ_TO_PTR(self->type);
1256
1257 struct class_lookup_data lookup = {
1258 .obj = MP_OBJ_TO_PTR(self->obj),
1259 .attr = attr,
1260 .meth_offset = 0,
1261 .dest = dest,
1262 .is_type = false,
1263 };
1264
1265 // Allow a call super().__init__() to reach any native base classes
1266 if (attr == MP_QSTR___init__) {
1267 lookup.meth_offset = offsetof(mp_obj_type_t, make_new);
1268 }
1269
1270 if (type->parent == NULL) {
1271 // no parents, do nothing
1272 #if MICROPY_MULTIPLE_INHERITANCE
1273 } else if (((mp_obj_base_t *)type->parent)->type == &mp_type_tuple) {
1274 const mp_obj_tuple_t *parent_tuple = type->parent;
1275 size_t len = parent_tuple->len;
1276 const mp_obj_t *items = parent_tuple->items;
1277 for (size_t i = 0; i < len; i++) {
1278 assert(mp_obj_is_type(items[i], &mp_type_type));
1279 if (MP_OBJ_TO_PTR(items[i]) == &mp_type_object) {
1280 // The "object" type will be searched at the end of this function,
1281 // and we don't want to lookup native methods in object.
1282 continue;
1283 }
1284 mp_obj_class_lookup(&lookup, (mp_obj_type_t *)MP_OBJ_TO_PTR(items[i]));
1285 if (dest[0] != MP_OBJ_NULL) {
1286 break;
1287 }
1288 }
1289 #endif
1290 } else if (type->parent != &mp_type_object) {
1291 mp_obj_class_lookup(&lookup, type->parent);
1292 }
1293
1294 if (dest[0] != MP_OBJ_NULL) {
1295 if (dest[0] == MP_OBJ_SENTINEL) {
1296 // Looked up native __init__ so defer to it
1297 dest[0] = MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj);
1298 dest[1] = self->obj;
1299 }
1300 return;
1301 }
1302
1303 // Reset meth_offset so we don't look up any native methods in object,
1304 // because object never takes up the native base-class slot.
1305 lookup.meth_offset = 0;
1306
1307 mp_obj_class_lookup(&lookup, &mp_type_object);
1308}
1309
1310const mp_obj_type_t mp_type_super = {
1311 { &mp_type_type },
1312 .name = MP_QSTR_super,
1313 .print = super_print,
1314 .make_new = super_make_new,
1315 .attr = super_attr,
1316};
1317
1318void mp_load_super_method(qstr attr, mp_obj_t *dest) {
1319 mp_obj_super_t super = {{&mp_type_super}, dest[1], dest[2]};
1320 mp_load_method(MP_OBJ_FROM_PTR(&super), attr, dest);
1321}
1322
1323/******************************************************************************/
1324// subclassing and built-ins specific to types
1325
1326// object and classinfo should be type objects
1327// (but the function will fail gracefully if they are not)
1328bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) {
1329 for (;;) {
1330 if (object == classinfo) {
1331 return true;
1332 }
1333
1334 // not equivalent classes, keep searching base classes
1335
1336 // object should always be a type object, but just return false if it's not
1337 if (!mp_obj_is_type(object, &mp_type_type)) {
1338 return false;
1339 }
1340
1341 const mp_obj_type_t *self = MP_OBJ_TO_PTR(object);
1342
1343 if (self->parent == NULL) {
1344 // type has no parents
1345 return false;
1346 #if MICROPY_MULTIPLE_INHERITANCE
1347 } else if (((mp_obj_base_t *)self->parent)->type == &mp_type_tuple) {
1348 // get the base objects (they should be type objects)
1349 const mp_obj_tuple_t *parent_tuple = self->parent;
1350 const mp_obj_t *item = parent_tuple->items;
1351 const mp_obj_t *top = item + parent_tuple->len - 1;
1352
1353 // iterate through the base objects
1354 for (; item < top; ++item) {
1355 if (mp_obj_is_subclass_fast(*item, classinfo)) {
1356 return true;
1357 }
1358 }
1359
1360 // search last base (simple tail recursion elimination)
1361 object = *item;
1362 #endif
1363 } else {
1364 // type has 1 parent
1365 object = MP_OBJ_FROM_PTR(self->parent);
1366 }
1367 }
1368}
1369
1370STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) {
1371 size_t len;
1372 mp_obj_t *items;
1373 if (mp_obj_is_type(classinfo, &mp_type_type)) {
1374 len = 1;
1375 items = &classinfo;
1376 } else if (mp_obj_is_type(classinfo, &mp_type_tuple)) {
1377 mp_obj_tuple_get(classinfo, &len, &items);
1378 } else {
1379 mp_raise_TypeError(MP_ERROR_TEXT("issubclass() arg 2 must be a class or a tuple of classes"));
1380 }
1381
1382 for (size_t i = 0; i < len; i++) {
1383 // We explicitly check for 'object' here since no-one explicitly derives from it
1384 if (items[i] == MP_OBJ_FROM_PTR(&mp_type_object) || mp_obj_is_subclass_fast(object, items[i])) {
1385 return mp_const_true;
1386 }
1387 }
1388 return mp_const_false;
1389}
1390
1391STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) {
1392 if (!mp_obj_is_type(object, &mp_type_type)) {
1393 mp_raise_TypeError(MP_ERROR_TEXT("issubclass() arg 1 must be a class"));
1394 }
1395 return mp_obj_is_subclass(object, classinfo);
1396}
1397
1398MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj, mp_builtin_issubclass);
1399
1400STATIC mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) {
1401 return mp_obj_is_subclass(MP_OBJ_FROM_PTR(mp_obj_get_type(object)), classinfo);
1402}
1403
1404MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance);
1405
1406mp_obj_t mp_obj_cast_to_native_base(mp_obj_t self_in, mp_const_obj_t native_type) {
1407 const mp_obj_type_t *self_type = mp_obj_get_type(self_in);
1408
1409 if (MP_OBJ_FROM_PTR(self_type) == native_type) {
1410 return self_in;
1411 } else if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(self_type), native_type)) {
1412 return MP_OBJ_NULL;
1413 } else {
1414 mp_obj_instance_t *self = (mp_obj_instance_t *)MP_OBJ_TO_PTR(self_in);
1415 return self->subobj[0];
1416 }
1417}
1418
1419/******************************************************************************/
1420// staticmethod and classmethod types (probably should go in a different file)
1421
1422STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) {
1423 assert(self == &mp_type_staticmethod || self == &mp_type_classmethod);
1424
1425 mp_arg_check_num(n_args, n_kw, 1, 1, false);
1426
1427 mp_obj_static_class_method_t *o = m_new_obj(mp_obj_static_class_method_t);
1428 *o = (mp_obj_static_class_method_t) {{self}, args[0]};
1429 return MP_OBJ_FROM_PTR(o);
1430}
1431
1432const mp_obj_type_t mp_type_staticmethod = {
1433 { &mp_type_type },
1434 .name = MP_QSTR_staticmethod,
1435 .make_new = static_class_method_make_new,
1436};
1437
1438const mp_obj_type_t mp_type_classmethod = {
1439 { &mp_type_type },
1440 .name = MP_QSTR_classmethod,
1441 .make_new = static_class_method_make_new,
1442};
1443