objtype.c 19.5 KB
Newer Older
1
2
#include <string.h>
#include <assert.h>
3
4
5
6

#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
7
#include "qstr.h"
8
#include "obj.h"
9
#include "runtime0.h"
10
11
12
13
14
15
16
17
18
19
20
#include "runtime.h"

/******************************************************************************/
// class object
// creating an instance of a class makes one of these objects

typedef struct _mp_obj_class_t {
    mp_obj_base_t base;
    mp_map_t members;
} mp_obj_class_t;

21
STATIC mp_obj_t mp_obj_new_class(mp_obj_t class) {
22
23
24
25
26
27
    mp_obj_class_t *o = m_new_obj(mp_obj_class_t);
    o->base.type = class;
    mp_map_init(&o->members, 0);
    return o;
}

28
// will return MP_OBJ_NULL if not found
29
STATIC mp_obj_t mp_obj_class_lookup(const mp_obj_type_t *type, qstr attr) {
30
    for (;;) {
31
        if (type->locals_dict != NULL) {
32
            // search locals_dict (the set of methods/attributes)
33
            assert(MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)); // Micro Python restriction, for now
34
            mp_map_t *locals_map = mp_obj_dict_get_map(type->locals_dict);
35
36
37
38
            mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
            if (elem != NULL) {
                return elem->value;
            }
39
40
41
42
43
        }

        // attribute not found, keep searching base classes

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

        uint len;
        mp_obj_t *items;
50
        mp_obj_tuple_get(type->bases_tuple, &len, &items);
51
52
53
54
        if (len == 0) {
            return NULL;
        }
        for (uint i = 0; i < len - 1; i++) {
55
            assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
56
57
58
            mp_obj_t obj = mp_obj_class_lookup((mp_obj_type_t*)items[i], attr);
            if (obj != MP_OBJ_NULL) {
                return obj;
59
60
61
62
            }
        }

        // search last base (simple tail recursion elimination)
63
        assert(MP_OBJ_IS_TYPE(items[len - 1], &mp_type_type));
64
        type = (mp_obj_type_t*)items[len - 1];
65
66
67
    }
}

68
STATIC void class_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
69
70
71
72
73
74
75
76
77
    mp_obj_class_t *self = self_in;
    qstr meth = (kind == PRINT_STR) ? MP_QSTR___str__ : MP_QSTR___repr__;
    mp_obj_t member = mp_obj_class_lookup(self->base.type, meth);
    if (member == MP_OBJ_NULL && kind == PRINT_STR) {
        // If there's no __str__, fall back to __repr__
        member = mp_obj_class_lookup(self->base.type, MP_QSTR___repr__);
    }

    if (member != MP_OBJ_NULL) {
Damien George's avatar
Damien George committed
78
        mp_obj_t r = mp_call_function_1(member, self_in);
79
80
81
82
83
        mp_obj_print_helper(print, env, r, PRINT_STR);
        return;
    }

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

87
STATIC mp_obj_t class_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
88
    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type));
89
    mp_obj_type_t *self = self_in;
90
91
92
93

    mp_obj_t o = mp_obj_new_class(self_in);

    // look for __init__ function
94
    mp_obj_t init_fn = mp_obj_class_lookup(self, MP_QSTR___init__);
95

96
    if (init_fn != MP_OBJ_NULL) {
97
98
        // call __init__ function
        mp_obj_t init_ret;
99
        if (n_args == 0 && n_kw == 0) {
Damien George's avatar
Damien George committed
100
            init_ret = mp_call_function_n_kw(init_fn, 1, 0, (mp_obj_t*)&o);
101
        } else {
102
103
104
            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));
Damien George's avatar
Damien George committed
105
            init_ret = mp_call_function_n_kw(init_fn, n_args + 1, n_kw, args2);
106
            m_del(mp_obj_t, args2, 1 + n_args + 2 * n_kw);
107
108
        }
        if (init_ret != mp_const_none) {
109
            nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret)));
110
111
112
113
114
        }

    } else {
        // TODO
        if (n_args != 0) {
115
            nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes 0 positional arguments but %d were given", n_args));
116
117
118
119
120
121
        }
    }

    return o;
}

122
STATIC const qstr unary_op_method_name[] = {
Damien George's avatar
Damien George committed
123
124
125
126
127
128
    [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
129
130
};

131
STATIC mp_obj_t class_unary_op(int op, mp_obj_t self_in) {
132
133
134
135
136
137
138
    mp_obj_class_t *self = self_in;
    qstr op_name = unary_op_method_name[op];
    if (op_name == 0) {
        return MP_OBJ_NULL;
    }
    mp_obj_t member = mp_obj_class_lookup(self->base.type, op_name);
    if (member != MP_OBJ_NULL) {
Damien George's avatar
Damien George committed
139
        return mp_call_function_1(member, self_in);
140
141
142
143
144
    } else {
        return MP_OBJ_NULL;
    }
}

145
STATIC const qstr binary_op_method_name[] = {
Damien George's avatar
Damien George committed
146
    [MP_BINARY_OP_SUBSCR] = MP_QSTR___getitem__,
147
    /*
Damien George's avatar
Damien George committed
148
149
150
151
152
    MP_BINARY_OP_OR,
    MP_BINARY_OP_XOR,
    MP_BINARY_OP_AND,
    MP_BINARY_OP_LSHIFT,
    MP_BINARY_OP_RSHIFT,
153
    */
Damien George's avatar
Damien George committed
154
155
    [MP_BINARY_OP_ADD] = MP_QSTR___add__,
    [MP_BINARY_OP_SUBTRACT] = MP_QSTR___sub__,
156
    /*
Damien George's avatar
Damien George committed
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
    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,
182
    */
Damien George's avatar
Damien George committed
183
    [MP_BINARY_OP_EXCEPTION_MATCH] = MP_QSTR_, // not implemented, used to make sure array has full size
184
185
};

186
STATIC mp_obj_t class_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
187
    mp_obj_class_t *lhs = lhs_in;
188
189
    qstr op_name = binary_op_method_name[op];
    if (op_name == 0) {
190
191
        return MP_OBJ_NULL;
    }
192
    mp_obj_t member = mp_obj_class_lookup(lhs->base.type, op_name);
193
    if (member != MP_OBJ_NULL) {
Damien George's avatar
Damien George committed
194
        return mp_call_function_2(member, lhs_in, rhs_in);
195
196
197
198
199
    } else {
        return MP_OBJ_NULL;
    }
}

200
STATIC void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
201
202
203
204
205
    // logic: look in obj members then class locals (TODO check this against CPython)
    mp_obj_class_t *self = self_in;
    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
206
        dest[0] = elem->value;
207
208
        return;
    }
209
210
    mp_obj_t member = mp_obj_class_lookup(self->base.type, attr);
    if (member != MP_OBJ_NULL) {
211
212
213
214
215
216
217
218
219
220
221
222
223
224
        // check if the methods are functions, static or class methods
        // see http://docs.python.org/3.3/howto/descriptor.html
        // TODO check that this is the correct place to have this logic
        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_in);
        } else if (mp_obj_is_callable(member)) {
            // return a bound method, with self being this object
            dest[0] = member;
            dest[1] = self_in;
225
226
        } else {
            // class member is a value, so just return that value
227
            dest[0] = member;
228
229
230
231
232
            return;
        }
    }
}

233
STATIC bool class_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
234
    mp_obj_class_t *self = self_in;
235
    mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
236
237
238
    return true;
}

239
240
bool class_store_item(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
    mp_obj_class_t *self = self_in;
241
    mp_obj_t member = mp_obj_class_lookup(self->base.type, MP_QSTR___setitem__);
242
    if (member != MP_OBJ_NULL) {
243
        mp_obj_t args[3] = {self_in, index, value};
Damien George's avatar
Damien George committed
244
        mp_call_function_n_kw(member, 3, 0, args);
245
        return true;
246
    } else {
247
        return false;
248
249
250
    }
}

251
252
253
/******************************************************************************/
// type object
//  - the struct is mp_obj_type_t and is defined in obj.h so const types can be made
254
//  - there is a constant mp_obj_type_t (called mp_type_type) for the 'type' object
255
//  - creating a new class (a new type) creates a new mp_obj_type_t
256

257
STATIC void type_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
258
    mp_obj_type_t *self = self_in;
259
    print(env, "<class '%s'>", qstr_str(self->name));
260
261
}

262
STATIC mp_obj_t type_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
263
264
    // TODO check n_kw == 0

265
266
267
268
269
    switch (n_args) {
        case 1:
            return mp_obj_get_type(args[0]);

        case 3:
270
            // args[0] = name
271
            // args[1] = bases tuple
272
            // args[2] = locals dict
273
            return mp_obj_new_type(mp_obj_str_get_qstr(args[0]), args[1], args[2]);
274
275

        default:
276
            nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "type takes 1 or 3 arguments"));
277
278
279
    }
}

280
STATIC mp_obj_t type_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
281
282
    // instantiate an instance of a class

283
    mp_obj_type_t *self = self_in;
284
285

    if (self->make_new == NULL) {
286
        nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "cannot create '%s' instances", qstr_str(self->name)));
287
    }
288
289

    // make new instance
290
    mp_obj_t o = self->make_new(self, n_args, n_kw, args);
291
292
293
294
295

    // return new instance
    return o;
}

296
// for fail, do nothing; for attr, dest[0] = value; for method, dest[0] = method, dest[1] = self
297
STATIC void type_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
298
    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type));
299
    mp_obj_type_t *self = self_in;
300
#if MICROPY_CPYTHON_COMPAT
301
302
303
304
    if (attr == MP_QSTR___name__) {
        dest[0] = MP_OBJ_NEW_QSTR(self->name);
        return;
    }
305
#endif
306
307
308
309
310
311
    mp_obj_t member = mp_obj_class_lookup(self, attr);
    if (member != MP_OBJ_NULL) {
        // check if the methods are functions, static or class methods
        // see http://docs.python.org/3.3/howto/descriptor.html
        if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) {
            // return just the function
312
            dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
313
314
        } else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) {
            // return a bound method, with self being this class
315
            dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
316
317
318
319
320
            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
            dest[0] = (mp_obj_t)member;
321
322
        }
    }
323
324
}

325
STATIC bool type_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
326
    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type));
327
328
    mp_obj_type_t *self = self_in;

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

331
    if (self->locals_dict != NULL) {
332
        assert(MP_OBJ_IS_TYPE(self->locals_dict, &mp_type_dict)); // Micro Python restriction, for now
333
334
335
336
337
338
339
        mp_map_t *locals_map = mp_obj_dict_get_map(self->locals_dict);
        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;
        }
340
    }
341
342

    return false;
343
344
}

345
346
const mp_obj_type_t mp_type_type = {
    { &mp_type_type },
347
    .name = MP_QSTR_type,
348
    .print = type_print,
349
    .make_new = type_make_new,
350
    .call = type_call,
351
352
    .load_attr = type_load_attr,
    .store_attr = type_store_attr,
353
};
354

355
mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) {
356
    assert(MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)); // Micro Python restriction, for now
357
    assert(MP_OBJ_IS_TYPE(locals_dict, &mp_type_dict)); // Micro Python restriction, for now
358
    mp_obj_type_t *o = m_new0(mp_obj_type_t, 1);
359
    o->base.type = &mp_type_type;
360
    o->name = name;
361
362
    o->print = class_print;
    o->make_new = class_make_new;
363
    o->unary_op = class_unary_op;
364
    o->binary_op = class_binary_op;
365
366
    o->load_attr = class_load_attr;
    o->store_attr = class_store_attr;
367
    o->store_item = class_store_item;
368
369
    o->bases_tuple = bases_tuple;
    o->locals_dict = locals_dict;
370
371
    return o;
}
372
373

/******************************************************************************/
Damien George's avatar
Damien George committed
374
375
376
377
378
379
380
381
// 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;

382
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
383
384
385
386
387
388
389
390
    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, ">");
}

391
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
392
393
394
    if (n_args != 2 || n_kw != 0) {
        // 0 arguments are turned into 2 in the compiler
        // 1 argument is not yet implemented
395
        nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "super() requires 2 arguments"));
Damien George's avatar
Damien George committed
396
397
398
399
400
    }
    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
401
STATIC void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
402
    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_super));
Damien George's avatar
Damien George committed
403
404
    mp_obj_super_t *self = self_in;

405
    assert(MP_OBJ_IS_TYPE(self->type, &mp_type_type));
Damien George's avatar
Damien George committed
406
407
408
409
410
411
412
413
414
415
416
417

    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++) {
418
        assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
Damien George's avatar
Damien George committed
419
420
421
        mp_obj_t member = mp_obj_class_lookup((mp_obj_type_t*)items[i], attr);
        if (member != MP_OBJ_NULL) {
            // XXX this and the code in class_load_attr need to be factored out
422
423
424
425
426
427
428
429
430
431
432
433
434
435
            // check if the methods are functions, static or class methods
            // see http://docs.python.org/3.3/howto/descriptor.html
            // TODO check that this is the correct place to have this logic
            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->obj);
            } if (mp_obj_is_callable(member)) {
                // return a bound method, with self being this object
                dest[0] = member;
                dest[1] = self->obj;
Damien George's avatar
Damien George committed
436
437
438
439
            } else {
                // class member is a value, so just return that value
                dest[0] = member;
            }
440
            return;
Damien George's avatar
Damien George committed
441
442
443
444
        }
    }
}

445
const mp_obj_type_t mp_type_super = {
446
    { &mp_type_type },
447
    .name = MP_QSTR_super,
Damien George's avatar
Damien George committed
448
449
450
451
452
453
454
    .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);
455
    *o = (mp_obj_super_t){{&mp_type_super}, type, obj};
Damien George's avatar
Damien George committed
456
457
458
459
    return o;
}

/******************************************************************************/
460
// subclassing and built-ins specific to types
461

462
463
// object and classinfo should be type objects
// (but the function will fail gracefully if they are not)
464
bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) {
465
466
    for (;;) {
        if (object == classinfo) {
467
            return true;
468
469
470
471
        }

        // not equivalent classes, keep searching base classes

472
473
474
475
476
        // 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;
        }

477
        const mp_obj_type_t *self = object;
478
479
480

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

484
        // get the base objects (they should be type objects)
485
486
487
488
        uint len;
        mp_obj_t *items;
        mp_obj_tuple_get(self->bases_tuple, &len, &items);
        if (len == 0) {
489
            return false;
490
        }
491
492

        // iterate through the base objects
493
        for (uint i = 0; i < len - 1; i++) {
494
            if (mp_obj_is_subclass_fast(items[i], classinfo)) {
495
                return true;
496
497
498
499
500
501
502
503
            }
        }

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

504
505
506
507
508
509
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;
510
    } else if (MP_OBJ_IS_TYPE(classinfo, &mp_type_tuple)) {
511
512
513
        mp_obj_tuple_get(classinfo, &len, &items);
    } else {
        nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 2 must be a class or a tuple of classes"));
514
515
    }

516
517
518
519
    for (uint i = 0; i < len; i++) {
        if (mp_obj_is_subclass_fast(object, items[i])) {
            return mp_const_true;
        }
520
    }
521
    return mp_const_false;
522
523
}

524
STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) {
525
526
527
528
    if (!MP_OBJ_IS_TYPE(object, &mp_type_type)) {
        nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 1 must be a class"));
    }
    return mp_obj_is_subclass(object, classinfo);
529
530
}

531
532
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj, mp_builtin_issubclass);

533
STATIC mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) {
534
    return mp_obj_is_subclass(mp_obj_get_type(object), classinfo);
535
536
537
}

MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance);
538
539
540
541

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

542
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) {
543
544
545
    assert(self_in == &mp_type_staticmethod || self_in == &mp_type_classmethod);

    if (n_args != 1 || n_kw != 0) {
546
        nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes 1 positional argument but %d were given", n_args));
547
548
549
550
551
552
553
    }

    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;
}

554
const mp_obj_type_t mp_type_staticmethod = {
555
    { &mp_type_type },
556
    .name = MP_QSTR_staticmethod,
557
    .make_new = static_class_method_make_new
558
559
560
};

const mp_obj_type_t mp_type_classmethod = {
561
    { &mp_type_type },
562
    .name = MP_QSTR_classmethod,
563
    .make_new = static_class_method_make_new
564
};