objtype.c 57 KB

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