4949/******************************************************************************/
5050// instance object
5151
52+ #define is_instance_type (type ) ((type)->make_new == instance_make_new)
5253#define is_native_type (type ) ((type)->make_new != instance_make_new)
5354STATIC mp_obj_t instance_make_new (mp_obj_t self_in , uint n_args , uint n_kw , const mp_obj_t * args );
55+ STATIC void instance_convert_return_attr (mp_obj_t self , const mp_obj_type_t * type , mp_obj_t member , mp_obj_t * dest );
5456
5557STATIC mp_obj_t mp_obj_new_instance (mp_obj_t class , uint subobjs ) {
5658 mp_obj_instance_t * o = m_new_obj_var (mp_obj_instance_t , mp_obj_t , subobjs );
@@ -120,10 +122,10 @@ STATIC void mp_obj_class_lookup(mp_obj_instance_t *o, const mp_obj_type_t *type,
120122 if (elem != NULL ) {
121123 dest [0 ] = elem -> value ;
122124 if (o != MP_OBJ_NULL && is_native_type (type )) {
123- dest [1 ] = o -> subobj [0 ];
125+ instance_convert_return_attr (o -> subobj [0 ], type , elem -> value , dest );
126+ } else {
127+ instance_convert_return_attr (o , type , elem -> value , dest );
124128 }
125- // TODO: Sensibly, we should call instance_convert_return_attr() here,
126- // instead of multiple places later. Also, this code duplicates runtime.c much.
127129 return ;
128130 }
129131 }
@@ -216,38 +218,56 @@ STATIC mp_obj_t instance_make_new(mp_obj_t self_in, uint n_args, uint n_kw, cons
216218
217219 mp_obj_instance_t * o = mp_obj_new_instance (self_in , num_native_bases );
218220
219- // look for __init__ function
221+ // look for __new__ function
220222 mp_obj_t init_fn [2 ] = {MP_OBJ_NULL };
221- mp_obj_class_lookup (NULL , self , MP_QSTR___init__ , offsetof(mp_obj_type_t , make_new ), init_fn );
223+ mp_obj_class_lookup (NULL , self , MP_QSTR___new__ , offsetof(mp_obj_type_t , make_new ), init_fn );
222224
225+ mp_obj_t new_ret = o ;
223226 if (init_fn [0 ] == MP_OBJ_SENTINEL ) {
224227 // Native type's constructor is what wins - it gets all our arguments,
225228 // and none Python classes are initialized at all.
226229 o -> subobj [0 ] = native_base -> make_new ((mp_obj_type_t * )native_base , n_args , n_kw , args );
227230 } else if (init_fn [0 ] != MP_OBJ_NULL ) {
228- // We need to default-initialize any native subobjs first
229- if (num_native_bases > 0 ) {
230- o -> subobj [0 ] = native_base -> make_new ((mp_obj_type_t * )native_base , 0 , 0 , NULL );
231- }
232- // now call Python class __init__ function with all args
233- mp_obj_t init_ret ;
231+ // now call Python class __new__ function with all args
234232 if (n_args == 0 && n_kw == 0 ) {
235- init_ret = mp_call_function_n_kw (init_fn [0 ], 1 , 0 , (mp_obj_t * )(void * )& o );
233+ new_ret = mp_call_function_n_kw (init_fn [0 ], 1 , 0 , (mp_obj_t * )(void * )& self_in );
236234 } else {
237235 mp_obj_t * args2 = m_new (mp_obj_t , 1 + n_args + 2 * n_kw );
238- args2 [0 ] = o ;
236+ args2 [0 ] = self_in ;
239237 memcpy (args2 + 1 , args , (n_args + 2 * n_kw ) * sizeof (mp_obj_t ));
240- init_ret = mp_call_function_n_kw (init_fn [0 ], n_args + 1 , n_kw , args2 );
238+ new_ret = mp_call_function_n_kw (init_fn [0 ], n_args + 1 , n_kw , args2 );
241239 m_del (mp_obj_t , args2 , 1 + n_args + 2 * n_kw );
242240 }
241+
242+ }
243+
244+ // https://docs.python.org/3.4/reference/datamodel.html#object.__new__
245+ // "If __new__() does not return an instance of cls, then the new instance’s __init__() method will not be invoked."
246+ if (mp_obj_get_type (new_ret ) != self_in ) {
247+ return new_ret ;
248+ }
249+
250+ o = new_ret ;
251+
252+ // now call Python class __init__ function with all args
253+ init_fn [0 ] = init_fn [1 ] = NULL ;
254+ mp_obj_class_lookup (o , self , MP_QSTR___init__ , 0 , init_fn );
255+ if (init_fn [0 ] != MP_OBJ_NULL ) {
256+ mp_obj_t init_ret ;
257+ if (n_args == 0 && n_kw == 0 ) {
258+ init_ret = mp_call_method_n_kw (0 , 0 , init_fn );
259+ } else {
260+ mp_obj_t * args2 = m_new (mp_obj_t , 2 + n_args + 2 * n_kw );
261+ args2 [0 ] = init_fn [0 ];
262+ args2 [1 ] = init_fn [1 ];
263+ memcpy (args2 + 2 , args , (n_args + 2 * n_kw ) * sizeof (mp_obj_t ));
264+ init_ret = mp_call_method_n_kw (n_args , n_kw , args2 );
265+ m_del (mp_obj_t , args2 , 2 + n_args + 2 * n_kw );
266+ }
243267 if (init_ret != mp_const_none ) {
244268 nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_TypeError , "__init__() should return None, not '%s'" , mp_obj_get_type_str (init_ret )));
245269 }
246270
247- } else {
248- if (n_args != 0 ) {
249- nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_TypeError , "object() takes no parameters" ));
250- }
251271 }
252272
253273 return o ;
@@ -325,15 +345,15 @@ STATIC const qstr binary_op_method_name[] = {
325345// and put the result in the dest[] array for a possible method call.
326346// Conversion means dealing with static/class methods, callables, and values.
327347// see http://docs.python.org/3.3/howto/descriptor.html
328- STATIC void instance_convert_return_attr (mp_obj_t self , mp_obj_t member , mp_obj_t * dest ) {
348+ STATIC void instance_convert_return_attr (mp_obj_t self , const mp_obj_type_t * type , mp_obj_t member , mp_obj_t * dest ) {
329349 assert (dest [1 ] == NULL );
330350 if (MP_OBJ_IS_TYPE (member , & mp_type_staticmethod )) {
331351 // return just the function
332352 dest [0 ] = ((mp_obj_static_class_method_t * )member )-> fun ;
333353 } else if (MP_OBJ_IS_TYPE (member , & mp_type_classmethod )) {
334354 // return a bound method, with self being the type of this object
335355 dest [0 ] = ((mp_obj_static_class_method_t * )member )-> fun ;
336- dest [1 ] = mp_obj_get_type ( self ) ;
356+ dest [1 ] = ( mp_obj_t ) type ;
337357 } else if (MP_OBJ_IS_TYPE (member , & mp_type_type )) {
338358 // Don't try to bind types
339359 dest [0 ] = member ;
@@ -357,14 +377,11 @@ STATIC mp_obj_t instance_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
357377 return MP_OBJ_NOT_SUPPORTED;
358378 }
359379 */
360- mp_obj_t member [ 2 ] = {MP_OBJ_NULL };
361- mp_obj_class_lookup (lhs , lhs -> base .type , op_name , offsetof(mp_obj_type_t , binary_op ), member );
362- if (member [0 ] == MP_OBJ_SENTINEL ) {
380+ mp_obj_t dest [ 3 ] = {MP_OBJ_NULL };
381+ mp_obj_class_lookup (lhs , lhs -> base .type , op_name , offsetof(mp_obj_type_t , binary_op ), dest );
382+ if (dest [0 ] == MP_OBJ_SENTINEL ) {
363383 return mp_binary_op (op , lhs -> subobj [0 ], rhs_in );
364- } else if (member [0 ] != MP_OBJ_NULL ) {
365- mp_obj_t dest [3 ];
366- dest [1 ] = MP_OBJ_NULL ;
367- instance_convert_return_attr (lhs_in , member [0 ], dest );
384+ } else if (dest [0 ] != MP_OBJ_NULL ) {
368385 dest [2 ] = rhs_in ;
369386 return mp_call_method_n_kw (1 , 0 , dest );
370387 } else {
@@ -374,6 +391,7 @@ STATIC mp_obj_t instance_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
374391
375392STATIC void instance_load_attr (mp_obj_t self_in , qstr attr , mp_obj_t * dest ) {
376393 // logic: look in obj members then class locals (TODO check this against CPython)
394+ assert (is_instance_type (mp_obj_get_type (self_in )));
377395 mp_obj_instance_t * self = self_in ;
378396
379397 mp_map_elem_t * elem = mp_map_lookup (& self -> members , MP_OBJ_NEW_QSTR (attr ), MP_MAP_LOOKUP );
@@ -387,9 +405,8 @@ STATIC void instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
387405 mp_obj_class_lookup (self , self -> base .type , attr , 0 , dest );
388406 mp_obj_t member = dest [0 ];
389407 if (member != MP_OBJ_NULL ) {
390- if (0 ) {
391408#if MICROPY_ENABLE_PROPERTY
392- } else if (MP_OBJ_IS_TYPE (member , & mp_type_property )) {
409+ if (MP_OBJ_IS_TYPE (member , & mp_type_property )) {
393410 // object member is a property
394411 // delegate the store to the property
395412 // TODO should this be part of instance_convert_return_attr?
@@ -400,15 +417,8 @@ STATIC void instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
400417 dest [0 ] = mp_call_function_n_kw (proxy [0 ], 1 , 0 , & self_in );
401418 // TODO should we convert the returned value using instance_convert_return_attr?
402419 }
403- #endif
404- } else {
405- // not a property
406- // if we don't yet have bound method (supposedly from native base), go
407- // try to convert own attrs.
408- if (dest [1 ] == MP_OBJ_NULL ) {
409- instance_convert_return_attr (self_in , member , dest );
410- }
411420 }
421+ #endif
412422 return ;
413423 }
414424
@@ -516,7 +526,6 @@ STATIC mp_obj_t instance_getiter(mp_obj_t self_in) {
516526 mp_obj_class_lookup (self , self -> base .type , MP_QSTR___getitem__ , 0 , member );
517527 if (member [0 ] != MP_OBJ_NULL ) {
518528 // __getitem__ exists, create an iterator
519- instance_convert_return_attr (self_in , member [0 ], member );
520529 return mp_obj_new_getitem_iter (member );
521530 }
522531 return MP_OBJ_NULL ;
@@ -584,24 +593,7 @@ STATIC void type_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
584593 return ;
585594 }
586595#endif
587- mp_obj_t member [2 ] = {MP_OBJ_NULL };
588- mp_obj_class_lookup (NULL , self , attr , 0 , member );
589- if (member [0 ] != MP_OBJ_NULL ) {
590- // check if the methods are functions, static or class methods
591- // see http://docs.python.org/3.3/howto/descriptor.html
592- if (MP_OBJ_IS_TYPE (member [0 ], & mp_type_staticmethod )) {
593- // return just the function
594- dest [0 ] = ((mp_obj_static_class_method_t * )member [0 ])-> fun ;
595- } else if (MP_OBJ_IS_TYPE (member [0 ], & mp_type_classmethod )) {
596- // return a bound method, with self being this class
597- dest [0 ] = ((mp_obj_static_class_method_t * )member [0 ])-> fun ;
598- dest [1 ] = self_in ;
599- } else {
600- // return just the function
601- // TODO need to wrap in a type check for the first argument; eg list.append(1,1) needs to throw an exception
602- dest [0 ] = member [0 ];
603- }
604- }
596+ mp_obj_class_lookup (NULL , self , attr , 0 , dest );
605597}
606598
607599STATIC bool type_store_attr (mp_obj_t self_in , qstr attr , mp_obj_t value ) {
@@ -742,12 +734,7 @@ STATIC void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
742734 mp_obj_tuple_get (type -> bases_tuple , & len , & items );
743735 for (uint i = 0 ; i < len ; i ++ ) {
744736 assert (MP_OBJ_IS_TYPE (items [i ], & mp_type_type ));
745- mp_obj_t member [2 ] = {MP_OBJ_NULL };
746- mp_obj_class_lookup (self -> obj , (mp_obj_type_t * )items [i ], attr , 0 , member );
747- if (member [0 ] != MP_OBJ_NULL ) {
748- instance_convert_return_attr (self -> obj , member [0 ], dest );
749- return ;
750- }
737+ mp_obj_class_lookup (self -> obj , (mp_obj_type_t * )items [i ], attr , 0 , dest );
751738 }
752739}
753740
0 commit comments