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