objtype.c 19.4 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
301
302
303
    if (attr == MP_QSTR___name__) {
        dest[0] = MP_OBJ_NEW_QSTR(self->name);
        return;
    }
304
305
306
307
308
309
    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
310
            dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
311
312
        } else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) {
            // return a bound method, with self being this class
313
            dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
314
315
316
317
318
            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;
319
320
        }
    }
321
322
}

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

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

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

    return false;
341
342
}

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

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

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

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

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

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

    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++) {
416
        assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
Damien George's avatar
Damien George committed
417
418
419
        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
420
421
422
423
424
425
426
427
428
429
430
431
432
433
            // 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
434
435
436
437
            } else {
                // class member is a value, so just return that value
                dest[0] = member;
            }
438
            return;
Damien George's avatar
Damien George committed
439
440
441
442
        }
    }
}

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

/******************************************************************************/
458
// subclassing and built-ins specific to types
459

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

        // not equivalent classes, keep searching base classes

470
471
472
473
474
        // 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;
        }

475
        const mp_obj_type_t *self = object;
476
477
478

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

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

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

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

502
503
504
505
506
507
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;
508
    } else if (MP_OBJ_IS_TYPE(classinfo, &mp_type_tuple)) {
509
510
511
        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"));
512
513
    }

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

522
STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) {
523
524
525
526
    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);
527
528
}

529
530
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj, mp_builtin_issubclass);

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

MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance);
536
537
538
539

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

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

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

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

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

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