objtype.c 32 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * This file is part of the Micro Python project, http://micropython.org/
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2013, 2014 Damien P. George
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

27
28
#include <stdio.h>
#include <stddef.h>
29
30
#include <string.h>
#include <assert.h>
31

32
#include "mpconfig.h"
33
34
#include "nlr.h"
#include "misc.h"
35
#include "qstr.h"
36
#include "obj.h"
37
#include "runtime0.h"
38
#include "runtime.h"
39
#include "objtype.h"
40

41
42
43
44
45
46
47
#if 0 // print debugging info
#define DEBUG_PRINT (1)
#define DEBUG_printf DEBUG_printf
#else // don't print debugging info
#define DEBUG_printf(...) (void)0
#endif

48
/******************************************************************************/
49
// instance object
50

51
52
#define is_native_type(type) ((type)->make_new != instance_make_new)
STATIC mp_obj_t instance_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args);
53

54
STATIC mp_obj_t mp_obj_new_instance(mp_obj_t class, uint subobjs) {
55
    mp_obj_instance_t *o = m_new_obj_var(mp_obj_instance_t, mp_obj_t, subobjs);
56
57
    o->base.type = class;
    mp_map_init(&o->members, 0);
58
    mp_seq_clear(o->subobj, 0, subobjs, sizeof(*o->subobj));
59
60
61
    return o;
}

62
STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) {
63
64
65
66
67
68
69
    uint len;
    mp_obj_t *items;
    mp_obj_tuple_get(type->bases_tuple, &len, &items);

    int count = 0;
    for (uint i = 0; i < len; i++) {
        assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
70
71
72
73
74
75
        const mp_obj_type_t *bt = (const mp_obj_type_t *)items[i];
        if (bt == &mp_type_object) {
            // Not a "real" type
            continue;
        }
        if (is_native_type(bt)) {
76
77
78
            *last_native_base = items[i];
            count++;
        } else {
79
            count += instance_count_native_bases(items[i], last_native_base);
80
81
82
83
84
85
86
87
88
89
90
        }
    }

    return count;
}

// TODO
// This implements depth-first left-to-right MRO, which is not compliant with Python3 MRO
// http://python-history.blogspot.com/2010/06/method-resolution-order.html
// https://www.python.org/download/releases/2.3/mro/
//
91
// will return MP_OBJ_NULL if not found
92
93
94
95
96
// will return MP_OBJ_SENTINEL if special method was found in a native type base
// via slot id (meth_offset). As there can be only one native base, it's known that it
// applies to instance->subobj[0]. In most cases, we also don't need to know which type
// it was - because instance->subobj[0] is of that type. The only exception is when
// object is not yet constructed, then we need to know base native type to construct
97
// instance->subobj[0]. This case is handled via instance_count_native_bases() though.
98
STATIC void mp_obj_class_lookup(mp_obj_instance_t *o, const mp_obj_type_t *type, qstr attr, machine_uint_t meth_offset, mp_obj_t *dest) {
99
100
    assert(dest[0] == NULL);
    assert(dest[1] == NULL);
101
    for (;;) {
102
103
104
105
106
107
108
        // Optimize special method lookup for native types
        // This avoids extra method_name => slot lookup. On the other hand,
        // this should not be applied to class types, as will result in extra
        // lookup either.
        if (meth_offset != 0 && is_native_type(type)) {
            if (*(void**)((char*)type + meth_offset) != NULL) {
                DEBUG_printf("mp_obj_class_lookup: matched special meth slot for %s\n", qstr_str(attr));
109
110
                dest[0] = MP_OBJ_SENTINEL;
                return;
111
112
113
            }
        }

114
        if (type->locals_dict != NULL) {
115
            // search locals_dict (the set of methods/attributes)
116
            assert(MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)); // Micro Python restriction, for now
117
            mp_map_t *locals_map = mp_obj_dict_get_map(type->locals_dict);
118
119
            mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
            if (elem != NULL) {
120
121
122
123
                dest[0] = elem->value;
                if (o != MP_OBJ_NULL && is_native_type(type)) {
                    dest[1] = o->subobj[0];
                }
124
125
                // TODO: Sensibly, we should call instance_convert_return_attr() here,
                // instead of multiple places later. Also, this code duplicates runtime.c much.
126
                return;
127
            }
128
129
        }

130
        // Try this for completeness, but all native methods should be statically defined
131
        // in locals_dict, and would be handled by above.
132
133
134
        if (o != MP_OBJ_NULL && is_native_type(type)) {
            mp_load_method_maybe(o->subobj[0], attr, dest);
            if (dest[0] != MP_OBJ_NULL) {
135
                return;
136
137
138
            }
        }

139
140
141
        // attribute not found, keep searching base classes

        // for a const struct, this entry might be NULL
142
        if (type->bases_tuple == MP_OBJ_NULL) {
143
            return;
144
145
146
147
        }

        uint len;
        mp_obj_t *items;
148
        mp_obj_tuple_get(type->bases_tuple, &len, &items);
149
        if (len == 0) {
150
            return;
151
152
        }
        for (uint i = 0; i < len - 1; i++) {
153
            assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
154
155
156
157
158
159
            mp_obj_type_t *bt = (mp_obj_type_t*)items[i];
            if (bt == &mp_type_object) {
                // Not a "real" type
                continue;
            }
            mp_obj_class_lookup(o, bt, attr, meth_offset, dest);
160
161
            if (dest[0] != MP_OBJ_NULL) {
                return;
162
163
164
165
            }
        }

        // search last base (simple tail recursion elimination)
166
        assert(MP_OBJ_IS_TYPE(items[len - 1], &mp_type_type));
167
        type = (mp_obj_type_t*)items[len - 1];
168
169
170
171
        if (type == &mp_type_object) {
            // Not a "real" type
            return;
        }
172
173
174
    }
}

175
STATIC void instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
176
    mp_obj_instance_t *self = self_in;
177
    qstr meth = (kind == PRINT_STR) ? MP_QSTR___str__ : MP_QSTR___repr__;
178
179
180
    mp_obj_t member[2] = {MP_OBJ_NULL};
    mp_obj_class_lookup(self, self->base.type, meth, offsetof(mp_obj_type_t, print), member);
    if (member[0] == MP_OBJ_NULL && kind == PRINT_STR) {
181
        // If there's no __str__, fall back to __repr__
182
        mp_obj_class_lookup(self, self->base.type, MP_QSTR___repr__, 0, member);
183
184
    }

185
    if (member[0] == MP_OBJ_SENTINEL) {
186
187
188
189
190
191
192
193
194
        // Handle Exception subclasses specially
        if (mp_obj_is_native_exception_instance(self->subobj[0])) {
            if (kind != PRINT_STR) {
                print(env, "%s", qstr_str(self->base.type->name));
            }
            mp_obj_print_helper(print, env, self->subobj[0], kind | PRINT_EXC_SUBCLASS);
        } else {
            mp_obj_print_helper(print, env, self->subobj[0], kind);
        }
195
        return;
196
197
    }

198
199
    if (member[0] != MP_OBJ_NULL) {
        mp_obj_t r = mp_call_function_1(member[0], self_in);
200
201
202
203
204
        mp_obj_print_helper(print, env, r, PRINT_STR);
        return;
    }

    // TODO: CPython prints fully-qualified type name
205
206
207
    print(env, "<%s object at %p>", mp_obj_get_type_str(self_in), self_in);
}

208
STATIC mp_obj_t instance_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
209
    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type));
210
    mp_obj_type_t *self = self_in;
211

212
    const mp_obj_type_t *native_base;
213
    uint num_native_bases = instance_count_native_bases(self, &native_base);
214
    assert(num_native_bases < 2);
215

216
    mp_obj_instance_t *o = mp_obj_new_instance(self_in, num_native_bases);
217

218
    // look for __init__ function
219
220
    mp_obj_t init_fn[2] = {MP_OBJ_NULL};
    mp_obj_class_lookup(NULL, self, MP_QSTR___init__, offsetof(mp_obj_type_t, make_new), init_fn);
221

222
    if (init_fn[0] == MP_OBJ_SENTINEL) {
223
224
225
        // Native type's constructor is what wins - it gets all our arguments,
        // and none Python classes are initialized at all.
        o->subobj[0] = native_base->make_new((mp_obj_type_t*)native_base, n_args, n_kw, args);
226
    } else if (init_fn[0] != MP_OBJ_NULL) {
227
228
229
230
231
        // We need to default-initialize any native subobjs first
        if (num_native_bases > 0) {
            o->subobj[0] = native_base->make_new((mp_obj_type_t*)native_base, 0, 0, NULL);
        }
        // now call Python class __init__ function with all args
232
        mp_obj_t init_ret;
233
        if (n_args == 0 && n_kw == 0) {
234
            init_ret = mp_call_function_n_kw(init_fn[0], 1, 0, (mp_obj_t*)(void*)&o);
235
        } else {
236
237
238
            mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_args + 2 * n_kw);
            args2[0] = o;
            memcpy(args2 + 1, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t));
239
            init_ret = mp_call_function_n_kw(init_fn[0], n_args + 1, n_kw, args2);
240
            m_del(mp_obj_t, args2, 1 + n_args + 2 * n_kw);
241
242
        }
        if (init_ret != mp_const_none) {
243
            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret)));
244
245
246
247
        }

    } else {
        if (n_args != 0) {
248
            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object() takes no parameters"));
249
250
251
252
253
254
        }
    }

    return o;
}

255
STATIC const qstr unary_op_method_name[] = {
Damien George's avatar
Damien George committed
256
257
258
259
260
261
    [MP_UNARY_OP_BOOL] = MP_QSTR___bool__,
    [MP_UNARY_OP_LEN] = MP_QSTR___len__,
    //[MP_UNARY_OP_POSITIVE,
    //[MP_UNARY_OP_NEGATIVE,
    //[MP_UNARY_OP_INVERT,
    [MP_UNARY_OP_NOT] = MP_QSTR_, // don't need to implement this, used to make sure array has full size
262
263
};

264
STATIC mp_obj_t instance_unary_op(int op, mp_obj_t self_in) {
265
    mp_obj_instance_t *self = self_in;
266
    qstr op_name = unary_op_method_name[op];
267
    /* Still try to lookup native slot
268
    if (op_name == 0) {
269
        return MP_OBJ_NOT_SUPPORTED;
270
    }
271
    */
272
273
274
    mp_obj_t member[2] = {MP_OBJ_NULL};
    mp_obj_class_lookup(self, self->base.type, op_name, offsetof(mp_obj_type_t, unary_op), member);
    if (member[0] == MP_OBJ_SENTINEL) {
275
        return mp_unary_op(op, self->subobj[0]);
276
277
    } else if (member[0] != MP_OBJ_NULL) {
        return mp_call_function_1(member[0], self_in);
278
    } else {
279
        return MP_OBJ_NOT_SUPPORTED;
280
281
282
    }
}

283
STATIC const qstr binary_op_method_name[] = {
284
    /*
Damien George's avatar
Damien George committed
285
286
287
288
289
    MP_BINARY_OP_OR,
    MP_BINARY_OP_XOR,
    MP_BINARY_OP_AND,
    MP_BINARY_OP_LSHIFT,
    MP_BINARY_OP_RSHIFT,
290
    */
Damien George's avatar
Damien George committed
291
292
    [MP_BINARY_OP_ADD] = MP_QSTR___add__,
    [MP_BINARY_OP_SUBTRACT] = MP_QSTR___sub__,
293
    /*
Damien George's avatar
Damien George committed
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
    MP_BINARY_OP_MULTIPLY,
    MP_BINARY_OP_FLOOR_DIVIDE,
    MP_BINARY_OP_TRUE_DIVIDE,
    MP_BINARY_OP_MODULO,
    MP_BINARY_OP_POWER,
    MP_BINARY_OP_INPLACE_OR,
    MP_BINARY_OP_INPLACE_XOR,
    MP_BINARY_OP_INPLACE_AND,
    MP_BINARY_OP_INPLACE_LSHIFT,
    MP_BINARY_OP_INPLACE_RSHIFT,
    MP_BINARY_OP_INPLACE_ADD,
    MP_BINARY_OP_INPLACE_SUBTRACT,
    MP_BINARY_OP_INPLACE_MULTIPLY,
    MP_BINARY_OP_INPLACE_FLOOR_DIVIDE,
    MP_BINARY_OP_INPLACE_TRUE_DIVIDE,
    MP_BINARY_OP_INPLACE_MODULO,
    MP_BINARY_OP_INPLACE_POWER,
    MP_BINARY_OP_LESS,
    MP_BINARY_OP_MORE,
    MP_BINARY_OP_EQUAL,
    MP_BINARY_OP_LESS_EQUAL,
    MP_BINARY_OP_MORE_EQUAL,
    MP_BINARY_OP_NOT_EQUAL,
    MP_BINARY_OP_IN,
    MP_BINARY_OP_IS,
319
    */
Damien George's avatar
Damien George committed
320
    [MP_BINARY_OP_EXCEPTION_MATCH] = MP_QSTR_, // not implemented, used to make sure array has full size
321
322
};

323
324
325
326
// Given a member that was extracted from an instance, convert it correctly
// and put the result in the dest[] array for a possible method call.
// Conversion means dealing with static/class methods, callables, and values.
// see http://docs.python.org/3.3/howto/descriptor.html
327
STATIC void instance_convert_return_attr(mp_obj_t self, mp_obj_t member, mp_obj_t *dest) {
328
    assert(dest[1] == NULL);
329
330
331
332
333
334
335
    if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) {
        // return just the function
        dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
    } else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) {
        // return a bound method, with self being the type of this object
        dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
        dest[1] = mp_obj_get_type(self);
336
337
338
    } else if (MP_OBJ_IS_TYPE(member, &mp_type_type)) {
        // Don't try to bind types
        dest[0] = member;
339
340
341
342
343
344
345
346
347
348
    } else if (mp_obj_is_callable(member)) {
        // return a bound method, with self being this object
        dest[0] = member;
        dest[1] = self;
    } else {
        // class member is a value, so just return that value
        dest[0] = member;
    }
}

349
STATIC mp_obj_t instance_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
350
351
    // Note: For ducktyping, CPython does not look in the instance members or use
    // __getattr__ or __getattribute__.  It only looks in the class dictionary.
352
    mp_obj_instance_t *lhs = lhs_in;
353
    qstr op_name = binary_op_method_name[op];
354
    /* Still try to lookup native slot
355
    if (op_name == 0) {
356
        return MP_OBJ_NOT_SUPPORTED;
357
    }
358
    */
359
360
361
    mp_obj_t member[2] = {MP_OBJ_NULL};
    mp_obj_class_lookup(lhs, lhs->base.type, op_name, offsetof(mp_obj_type_t, binary_op), member);
    if (member[0] == MP_OBJ_SENTINEL) {
362
        return mp_binary_op(op, lhs->subobj[0], rhs_in);
363
    } else if (member[0] != MP_OBJ_NULL) {
364
365
        mp_obj_t dest[3];
        dest[1] = MP_OBJ_NULL;
366
        instance_convert_return_attr(lhs_in, member[0], dest);
367
368
        dest[2] = rhs_in;
        return mp_call_method_n_kw(1, 0, dest);
369
    } else {
370
        return MP_OBJ_NOT_SUPPORTED;
371
372
373
    }
}

374
STATIC void instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
375
    // logic: look in obj members then class locals (TODO check this against CPython)
376
    mp_obj_instance_t *self = self_in;
377

378
379
380
    mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
    if (elem != NULL) {
        // object member, always treated as a value
381
        // TODO should we check for properties?
382
        dest[0] = elem->value;
383
384
        return;
    }
385

386
387
    mp_obj_class_lookup(self, self->base.type, attr, 0, dest);
    mp_obj_t member = dest[0];
388
    if (member != MP_OBJ_NULL) {
389
390
391
392
393
        if (0) {
#if MICROPY_ENABLE_PROPERTY
        } else if (MP_OBJ_IS_TYPE(member, &mp_type_property)) {
            // object member is a property
            // delegate the store to the property
394
            // TODO should this be part of instance_convert_return_attr?
395
396
397
398
399
            const mp_obj_t *proxy = mp_obj_property_get(member);
            if (proxy[0] == mp_const_none) {
                // TODO
            } else {
                dest[0] = mp_call_function_n_kw(proxy[0], 1, 0, &self_in);
400
                // TODO should we convert the returned value using instance_convert_return_attr?
401
402
403
404
            }
#endif
        } else {
            // not a property
405
406
407
            // if we don't yet have bound method (supposedly from native base), go
            // try to convert own attrs.
            if (dest[1] == MP_OBJ_NULL) {
408
                instance_convert_return_attr(self_in, member, dest);
409
            }
410
        }
Damien George's avatar
Damien George committed
411
412
413
414
415
416
417
418
419
420
421
422
        return;
    }

    // try __getattr__
    if (attr != MP_QSTR___getattr__) {
        mp_obj_t dest2[3];
        mp_load_method_maybe(self_in, MP_QSTR___getattr__, dest2);
        if (dest2[0] != MP_OBJ_NULL) {
            // __getattr__ exists, call it and return its result
            // XXX if this fails to load the requested attr, should we catch the attribute error and return silently?
            dest2[2] = MP_OBJ_NEW_QSTR(attr);
            dest[0] = mp_call_method_n_kw(1, 0, dest2);
423
424
425
426
427
            return;
        }
    }
}

428
STATIC bool instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
429
    mp_obj_instance_t *self = self_in;
430
431
432
433

#if MICROPY_ENABLE_PROPERTY
    // for property, we need to do a lookup first in the class dict
    // this makes all stores slow... how to fix?
434
435
436
    mp_obj_t member[2] = {MP_OBJ_NULL};
    mp_obj_class_lookup(self, self->base.type, attr, 0, member);
    if (member[0] != MP_OBJ_NULL && MP_OBJ_IS_TYPE(member[0], &mp_type_property)) {
437
438
        // attribute already exists and is a property
        // delegate the store to the property
439
        const mp_obj_t *proxy = mp_obj_property_get(member[0]);
440
441
442
443
444
445
446
447
448
449
450
        if (proxy[1] == mp_const_none) {
            // TODO better error message
            return false;
        } else {
            mp_obj_t dest[2] = {self_in, value};
            mp_call_function_n_kw(proxy[1], 2, 0, dest);
            return true;
        }
    }
#endif

451
452
    if (value == MP_OBJ_NULL) {
        // delete attribute
453
454
        mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
        return elem != NULL;
455
456
457
458
459
    } else {
        // store attribute
        mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
        return true;
    }
460
461
}

462
STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
463
    mp_obj_instance_t *self = self_in;
464
    mp_obj_t member[2] = {MP_OBJ_NULL};
465
    uint meth_args;
466
467
    if (value == MP_OBJ_NULL) {
        // delete item
468
        mp_obj_class_lookup(self, self->base.type, MP_QSTR___delitem__, offsetof(mp_obj_type_t, subscr), member);
469
        meth_args = 2;
470
471
    } else if (value == MP_OBJ_SENTINEL) {
        // load item
472
        mp_obj_class_lookup(self, self->base.type, MP_QSTR___getitem__, offsetof(mp_obj_type_t, subscr), member);
473
        meth_args = 2;
474
    } else {
475
        // store item
476
        mp_obj_class_lookup(self, self->base.type, MP_QSTR___setitem__, offsetof(mp_obj_type_t, subscr), member);
477
        meth_args = 3;
478
    }
479
    if (member[0] == MP_OBJ_SENTINEL) {
480
        return mp_obj_subscr(self->subobj[0], index, value);
481
    } else if (member[0] != MP_OBJ_NULL) {
482
        mp_obj_t args[3] = {self_in, index, value};
483
        // TODO probably need to call instance_convert_return_attr, and use mp_call_method_n_kw
484
        mp_obj_t ret = mp_call_function_n_kw(member[0], meth_args, 0, args);
485
486
487
488
489
        if (value == MP_OBJ_SENTINEL) {
            return ret;
        } else {
            return mp_const_none;
        }
490
    } else {
491
        return MP_OBJ_NOT_SUPPORTED;
492
493
494
    }
}

495
STATIC mp_obj_t instance_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
496
    mp_obj_instance_t *self = self_in;
497
498
499
500
    mp_obj_t member[2] = {MP_OBJ_NULL};
    mp_obj_class_lookup(self, self->base.type, MP_QSTR___call__, offsetof(mp_obj_type_t, call), member);
    if (member[0] == MP_OBJ_NULL) {
        return MP_OBJ_NULL;
501
    }
502
    if (member[0] == MP_OBJ_SENTINEL) {
503
504
        return mp_call_function_n_kw(self->subobj[0], n_args, n_kw, args);
    }
505
    mp_obj_t meth = mp_obj_new_bound_meth(member[0], self);
506
507
508
    return mp_call_function_n_kw(meth, n_args, n_kw, args);
}

509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
STATIC mp_obj_t instance_getiter(mp_obj_t self_in) {
    mp_obj_instance_t *self = self_in;
    mp_obj_t member[2] = {MP_OBJ_NULL};
    mp_obj_class_lookup(self, self->base.type, MP_QSTR___iter__, offsetof(mp_obj_type_t, getiter), member);
    if (member[0] == MP_OBJ_NULL) {
        // This kinda duplicates code in mp_getiter()
        mp_obj_class_lookup(self, self->base.type, MP_QSTR___getitem__, 0, member);
        if (member[0] != MP_OBJ_NULL) {
            // __getitem__ exists, create an iterator
            instance_convert_return_attr(self_in, member[0], member);
            return mp_obj_new_getitem_iter(member);
        }
        return MP_OBJ_NULL;
    }
    if (member[0] == MP_OBJ_SENTINEL) {
        mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]);
        return type->getiter(self->subobj[0]);
    }
    mp_obj_t meth = mp_obj_new_bound_meth(member[0], self);
    return mp_call_function_n_kw(meth, 0, 0, NULL);
}

531
532
533
/******************************************************************************/
// type object
//  - the struct is mp_obj_type_t and is defined in obj.h so const types can be made
534
//  - there is a constant mp_obj_type_t (called mp_type_type) for the 'type' object
535
//  - creating a new class (a new type) creates a new mp_obj_type_t
536

537
STATIC void type_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
538
    mp_obj_type_t *self = self_in;
539
    print(env, "<class '%s'>", qstr_str(self->name));
540
541
}

542
STATIC mp_obj_t type_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
543
544
    // TODO check n_kw == 0

545
546
547
548
549
    switch (n_args) {
        case 1:
            return mp_obj_get_type(args[0]);

        case 3:
550
            // args[0] = name
551
            // args[1] = bases tuple
552
            // args[2] = locals dict
553
            return mp_obj_new_type(mp_obj_str_get_qstr(args[0]), args[1], args[2]);
554
555

        default:
556
            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "type takes 1 or 3 arguments"));
557
558
559
    }
}

560
STATIC mp_obj_t type_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
561
562
    // instantiate an instance of a class

563
    mp_obj_type_t *self = self_in;
564
565

    if (self->make_new == NULL) {
566
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "cannot create '%s' instances", qstr_str(self->name)));
567
    }
568
569

    // make new instance
570
    mp_obj_t o = self->make_new(self, n_args, n_kw, args);
571
572
573
574
575

    // return new instance
    return o;
}

576
// for fail, do nothing; for attr, dest[0] = value; for method, dest[0] = method, dest[1] = self
577
STATIC void type_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
578
    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type));
579
    mp_obj_type_t *self = self_in;
580
#if MICROPY_CPYTHON_COMPAT
581
582
583
584
    if (attr == MP_QSTR___name__) {
        dest[0] = MP_OBJ_NEW_QSTR(self->name);
        return;
    }
585
#endif
586
587
588
    mp_obj_t member[2] = {MP_OBJ_NULL};
    mp_obj_class_lookup(NULL, self, attr, 0, member);
    if (member[0] != MP_OBJ_NULL) {
589
590
        // check if the methods are functions, static or class methods
        // see http://docs.python.org/3.3/howto/descriptor.html
591
        if (MP_OBJ_IS_TYPE(member[0], &mp_type_staticmethod)) {
592
            // return just the function
593
594
            dest[0] = ((mp_obj_static_class_method_t*)member[0])->fun;
        } else if (MP_OBJ_IS_TYPE(member[0], &mp_type_classmethod)) {
595
            // return a bound method, with self being this class
596
            dest[0] = ((mp_obj_static_class_method_t*)member[0])->fun;
597
598
599
600
            dest[1] = self_in;
        } else {
            // return just the function
            // TODO need to wrap in a type check for the first argument; eg list.append(1,1) needs to throw an exception
601
            dest[0] = member[0];
602
603
        }
    }
604
605
}

606
STATIC bool type_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
607
    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type));
608
609
    mp_obj_type_t *self = self_in;

610
611
    // TODO CPython allows STORE_ATTR to a class, but is this the correct implementation?

612
    if (self->locals_dict != NULL) {
613
        assert(MP_OBJ_IS_TYPE(self->locals_dict, &mp_type_dict)); // Micro Python restriction, for now
614
        mp_map_t *locals_map = mp_obj_dict_get_map(self->locals_dict);
615
616
617
618
619
620
621
622
623
624
625
626
627
        if (value == MP_OBJ_NULL) {
            // delete attribute
            mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
            // note that locals_map may be in ROM, so remove will fail in that case
            return elem != NULL;
        } else {
            // store attribute
            mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
            // note that locals_map may be in ROM, so add will fail in that case
            if (elem != NULL) {
                elem->value = value;
                return true;
            }
628
        }
629
    }
630
631

    return false;
632
633
}

634
635
636
637
638
639
STATIC mp_obj_t type_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
    switch (op) {
        case MP_BINARY_OP_EQUAL:
            // Types can be equal only if it's the same type structure,
            // we don't even need to check for 2nd arg type.
            return MP_BOOL(lhs_in == rhs_in);
640
641
642

        default:
            return MP_OBJ_NOT_SUPPORTED;
643
644
645
    }
}

646
647
const mp_obj_type_t mp_type_type = {
    { &mp_type_type },
648
    .name = MP_QSTR_type,
649
    .print = type_print,
650
    .make_new = type_make_new,
651
    .call = type_call,
652
653
    .load_attr = type_load_attr,
    .store_attr = type_store_attr,
654
    .binary_op = type_binary_op,
655
};
656

657
mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) {
658
    assert(MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)); // Micro Python restriction, for now
659
    assert(MP_OBJ_IS_TYPE(locals_dict, &mp_type_dict)); // Micro Python restriction, for now
660
661
662
663
664
665
666
667
668
669
670
671
672
673

    // Basic validation of base classes
    uint len;
    mp_obj_t *items;
    mp_obj_tuple_get(bases_tuple, &len, &items);
    for (uint i = 0; i < len; i++) {
        assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
        mp_obj_type_t *t = items[i];
        // TODO: Verify with CPy, tested on function type
        if (t->make_new == NULL) {
            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "type '%s' is not an acceptable base type", qstr_str(t->name)));
        }
    }

674
    mp_obj_type_t *o = m_new0(mp_obj_type_t, 1);
675
    o->base.type = &mp_type_type;
676
    o->name = name;
677
678
679
680
681
682
683
684
    o->print = instance_print;
    o->make_new = instance_make_new;
    o->unary_op = instance_unary_op;
    o->binary_op = instance_binary_op;
    o->load_attr = instance_load_attr;
    o->store_attr = instance_store_attr;
    o->subscr = instance_subscr;
    o->call = instance_call;
685
    o->getiter = instance_getiter;
686
687
    o->bases_tuple = bases_tuple;
    o->locals_dict = locals_dict;
688
689

    const mp_obj_type_t *native_base;
690
    uint num_native_bases = instance_count_native_bases(o, &native_base);
691
692
693
694
    if (num_native_bases > 1) {
        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "multiple bases have instance lay-out conflict"));
    }

695
696
    return o;
}
697
698

/******************************************************************************/
Damien George's avatar
Damien George committed
699
700
701
702
703
704
705
706
// super object

typedef struct _mp_obj_super_t {
    mp_obj_base_t base;
    mp_obj_t type;
    mp_obj_t obj;
} mp_obj_super_t;

707
STATIC void super_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
Damien George's avatar
Damien George committed
708
709
710
711
712
713
714
715
    mp_obj_super_t *self = self_in;
    print(env, "<super: ");
    mp_obj_print_helper(print, env, self->type, PRINT_STR);
    print(env, ", ");
    mp_obj_print_helper(print, env, self->obj, PRINT_STR);
    print(env, ">");
}

716
STATIC mp_obj_t super_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
Damien George's avatar
Damien George committed
717
718
719
    if (n_args != 2 || n_kw != 0) {
        // 0 arguments are turned into 2 in the compiler
        // 1 argument is not yet implemented
720
        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "super() requires 2 arguments"));
Damien George's avatar
Damien George committed
721
722
723
724
725
    }
    return mp_obj_new_super(args[0], args[1]);
}

// for fail, do nothing; for attr, dest[0] = value; for method, dest[0] = method, dest[1] = self
726
STATIC void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
727
    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_super));
Damien George's avatar
Damien George committed
728
729
    mp_obj_super_t *self = self_in;

730
    assert(MP_OBJ_IS_TYPE(self->type, &mp_type_type));
Damien George's avatar
Damien George committed
731
732
733
734
735
736
737
738
739
740
741
742

    mp_obj_type_t *type = self->type;

    // for a const struct, this entry might be NULL
    if (type->bases_tuple == MP_OBJ_NULL) {
        return;
    }

    uint len;
    mp_obj_t *items;
    mp_obj_tuple_get(type->bases_tuple, &len, &items);
    for (uint i = 0; i < len; i++) {
743
        assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
744
745
746
        mp_obj_t member[2] = {MP_OBJ_NULL};
        mp_obj_class_lookup(self->obj, (mp_obj_type_t*)items[i], attr, 0, member);
        if (member[0] != MP_OBJ_NULL) {
747
            instance_convert_return_attr(self->obj, member[0], dest);
748
            return;
Damien George's avatar
Damien George committed
749
750
751
752
        }
    }
}

753
const mp_obj_type_t mp_type_super = {
754
    { &mp_type_type },
755
    .name = MP_QSTR_super,
Damien George's avatar
Damien George committed
756
757
758
759
760
761
762
    .print = super_print,
    .make_new = super_make_new,
    .load_attr = super_load_attr,
};

mp_obj_t mp_obj_new_super(mp_obj_t type, mp_obj_t obj) {
    mp_obj_super_t *o = m_new_obj(mp_obj_super_t);
763
    *o = (mp_obj_super_t){{&mp_type_super}, type, obj};
Damien George's avatar
Damien George committed
764
765
766
767
    return o;
}

/******************************************************************************/
768
// subclassing and built-ins specific to types
769

770
771
// object and classinfo should be type objects
// (but the function will fail gracefully if they are not)
772
bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) {
773
774
    for (;;) {
        if (object == classinfo) {
775
            return true;
776
777
778
779
        }

        // not equivalent classes, keep searching base classes

780
781
782
783
784
        // object should always be a type object, but just return false if it's not
        if (!MP_OBJ_IS_TYPE(object, &mp_type_type)) {
            return false;
        }

785
        const mp_obj_type_t *self = object;
786
787
788

        // for a const struct, this entry might be NULL
        if (self->bases_tuple == MP_OBJ_NULL) {
789
            return false;
790
791
        }

792
        // get the base objects (they should be type objects)
793
794
795
796
        uint len;
        mp_obj_t *items;
        mp_obj_tuple_get(self->bases_tuple, &len, &items);
        if (len == 0) {
797
            return false;
798
        }
799
800

        // iterate through the base objects
801
        for (uint i = 0; i < len - 1; i++) {
802
            if (mp_obj_is_subclass_fast(items[i], classinfo)) {
803
                return true;
804
805
806
807
808
809
810
811
            }
        }

        // search last base (simple tail recursion elimination)
        object = items[len - 1];
    }
}

812
813
814
815
816
817
STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) {
    uint len;
    mp_obj_t *items;
    if (MP_OBJ_IS_TYPE(classinfo, &mp_type_type)) {
        len = 1;
        items = &classinfo;
818
    } else if (MP_OBJ_IS_TYPE(classinfo, &mp_type_tuple)) {
819
820
        mp_obj_tuple_get(classinfo, &len, &items);
    } else {
821
        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 2 must be a class or a tuple of classes"));
822
823
    }

824
    for (uint i = 0; i < len; i++) {
825
826
        // We explicitly check for 'object' here since no-one explicitly derives from it
        if (items[i] == &mp_type_object || mp_obj_is_subclass_fast(object, items[i])) {
827
828
            return mp_const_true;
        }
829
    }
830
    return mp_const_false;
831
832
}

833
STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) {
834
    if (!MP_OBJ_IS_TYPE(object, &mp_type_type)) {
835
        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 1 must be a class"));
836
837
    }
    return mp_obj_is_subclass(object, classinfo);
838
839
}

840
841
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj, mp_builtin_issubclass);

842
STATIC mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) {
843
    return mp_obj_is_subclass(mp_obj_get_type(object), classinfo);
844
845
846
}

MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance);
847
848
849
850

/******************************************************************************/
// staticmethod and classmethod types (probably should go in a different file)

851
STATIC mp_obj_t static_class_method_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
852
853
854
    assert(self_in == &mp_type_staticmethod || self_in == &mp_type_classmethod);

    if (n_args != 1 || n_kw != 0) {
855
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes 1 positional argument but %d were given", n_args));
856
857
858
859
860
861
862
    }

    mp_obj_static_class_method_t *o = m_new_obj(mp_obj_static_class_method_t);
    *o = (mp_obj_static_class_method_t){{(mp_obj_type_t*)self_in}, args[0]};
    return o;
}

863
const mp_obj_type_t mp_type_staticmethod = {
864
    { &mp_type_type },
865
    .name = MP_QSTR_staticmethod,
866
    .make_new = static_class_method_make_new
867
868
869
};

const mp_obj_type_t mp_type_classmethod = {
870
    { &mp_type_type },
871
    .name = MP_QSTR_classmethod,
872
    .make_new = static_class_method_make_new
873
};