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

319
STATIC bool type_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
320
    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type));
321
322
    mp_obj_type_t *self = self_in;

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

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

    return false;
337
338
}

339
340
const mp_obj_type_t mp_type_type = {
    { &mp_type_type },
341
    .name = MP_QSTR_type,
342
    .print = type_print,
343
    .make_new = type_make_new,
344
    .call = type_call,
345
346
    .load_attr = type_load_attr,
    .store_attr = type_store_attr,
347
};
348

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

/******************************************************************************/
Damien George's avatar
Damien George committed
368
369
370
371
372
373
374
375
// 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;

376
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
377
378
379
380
381
382
383
384
    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, ">");
}

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

399
    assert(MP_OBJ_IS_TYPE(self->type, &mp_type_type));
Damien George's avatar
Damien George committed
400
401
402
403
404
405
406
407
408
409
410
411

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

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

/******************************************************************************/
454
// subclassing and built-ins specific to types
455

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

        // not equivalent classes, keep searching base classes

466
467
468
469
470
        // 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;
        }

471
        const mp_obj_type_t *self = object;
472
473
474

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

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

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

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

498
499
500
501
502
503
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;
504
    } else if (MP_OBJ_IS_TYPE(classinfo, &mp_type_tuple)) {
505
506
507
        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"));
508
509
    }

510
511
512
513
    for (uint i = 0; i < len; i++) {
        if (mp_obj_is_subclass_fast(object, items[i])) {
            return mp_const_true;
        }
514
    }
515
    return mp_const_false;
516
517
}

518
STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) {
519
520
521
522
    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);
523
524
}

525
526
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj, mp_builtin_issubclass);

527
STATIC mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) {
528
    return mp_obj_is_subclass(mp_obj_get_type(object), classinfo);
529
530
531
}

MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance);
532
533
534
535

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

536
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) {
537
538
539
    assert(self_in == &mp_type_staticmethod || self_in == &mp_type_classmethod);

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

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

548
const mp_obj_type_t mp_type_staticmethod = {
549
    { &mp_type_type },
550
    .name = MP_QSTR_staticmethod,
551
    .make_new = static_class_method_make_new
552
553
554
};

const mp_obj_type_t mp_type_classmethod = {
555
    { &mp_type_type },
556
    .name = MP_QSTR_classmethod,
557
    .make_new = static_class_method_make_new
558
};