@@ -362,6 +362,96 @@ mp_obj_t mp_obj_new_type(const char *name, mp_obj_t bases_tuple, mp_obj_t locals
362362 return o ;
363363}
364364
365+ /******************************************************************************/
366+ // super object
367+
368+ typedef struct _mp_obj_super_t {
369+ mp_obj_base_t base ;
370+ mp_obj_t type ;
371+ mp_obj_t obj ;
372+ } mp_obj_super_t ;
373+
374+ static void super_print (void (* print )(void * env , const char * fmt , ...), void * env , mp_obj_t self_in , mp_print_kind_t kind ) {
375+ mp_obj_super_t * self = self_in ;
376+ print (env , "<super: " );
377+ mp_obj_print_helper (print , env , self -> type , PRINT_STR );
378+ print (env , ", " );
379+ mp_obj_print_helper (print , env , self -> obj , PRINT_STR );
380+ print (env , ">" );
381+ }
382+
383+ static mp_obj_t super_make_new (mp_obj_t type_in , uint n_args , uint n_kw , const mp_obj_t * args ) {
384+ if (n_args != 2 || n_kw != 0 ) {
385+ // 0 arguments are turned into 2 in the compiler
386+ // 1 argument is not yet implemented
387+ nlr_jump (mp_obj_new_exception_msg (MP_QSTR_TypeError , "super() requires 2 arguments" ));
388+ }
389+ return mp_obj_new_super (args [0 ], args [1 ]);
390+ }
391+
392+ // for fail, do nothing; for attr, dest[0] = value; for method, dest[0] = method, dest[1] = self
393+ static void super_load_attr (mp_obj_t self_in , qstr attr , mp_obj_t * dest ) {
394+ assert (MP_OBJ_IS_TYPE (self_in , & super_type ));
395+ mp_obj_super_t * self = self_in ;
396+
397+ assert (MP_OBJ_IS_TYPE (self -> type , & mp_const_type ));
398+
399+ mp_obj_type_t * type = self -> type ;
400+
401+ // for a const struct, this entry might be NULL
402+ if (type -> bases_tuple == MP_OBJ_NULL ) {
403+ return ;
404+ }
405+
406+ uint len ;
407+ mp_obj_t * items ;
408+ mp_obj_tuple_get (type -> bases_tuple , & len , & items );
409+ for (uint i = 0 ; i < len ; i ++ ) {
410+ assert (MP_OBJ_IS_TYPE (items [i ], & mp_const_type ));
411+ mp_obj_t member = mp_obj_class_lookup ((mp_obj_type_t * )items [i ], attr );
412+ if (member != MP_OBJ_NULL ) {
413+ // XXX this and the code in class_load_attr need to be factored out
414+ if (mp_obj_is_callable (member )) {
415+ // class member is callable so build a bound method
416+ // check if the methods are functions, static or class methods
417+ // see http://docs.python.org/3.3/howto/descriptor.html
418+ // TODO check that this is the correct place to have this logic
419+ if (MP_OBJ_IS_TYPE (member , & mp_type_staticmethod )) {
420+ // return just the function
421+ dest [0 ] = ((mp_obj_staticmethod_t * )member )-> fun ;
422+ } else if (MP_OBJ_IS_TYPE (member , & mp_type_classmethod )) {
423+ // return a bound method, with self being the type of this object
424+ dest [0 ] = ((mp_obj_classmethod_t * )member )-> fun ;
425+ dest [1 ] = mp_obj_get_type (self -> obj );
426+ } else {
427+ // return a bound method, with self being this object
428+ dest [0 ] = member ;
429+ dest [1 ] = self -> obj ;
430+ }
431+ return ;
432+ } else {
433+ // class member is a value, so just return that value
434+ dest [0 ] = member ;
435+ return ;
436+ }
437+ }
438+ }
439+ }
440+
441+ const mp_obj_type_t super_type = {
442+ { & mp_const_type },
443+ "super" ,
444+ .print = super_print ,
445+ .make_new = super_make_new ,
446+ .load_attr = super_load_attr ,
447+ };
448+
449+ mp_obj_t mp_obj_new_super (mp_obj_t type , mp_obj_t obj ) {
450+ mp_obj_super_t * o = m_new_obj (mp_obj_super_t );
451+ * o = (mp_obj_super_t ){{& super_type }, type , obj };
452+ return o ;
453+ }
454+
365455/******************************************************************************/
366456// built-ins specific to types
367457
0 commit comments