@@ -14,7 +14,7 @@ use crate::pyobject::{
1414 IdProtocol , PyAttributes , PyClassImpl , PyContext , PyIterable , PyObject , PyObjectRef , PyRef ,
1515 PyResult , PyValue , TypeProtocol ,
1616} ;
17- use crate :: slots:: { PyClassSlots , PyTpFlags } ;
17+ use crate :: slots:: { PyClassSlot , PyTpFlags } ;
1818use crate :: vm:: VirtualMachine ;
1919
2020/// type(object_or_name, bases, dict)
@@ -24,11 +24,12 @@ use crate::vm::VirtualMachine;
2424#[ derive( Debug ) ]
2525pub struct PyClass {
2626 pub name : String ,
27- pub bases : Vec < PyClassRef > ,
27+ pub base : Option < PyClassRef > , // tp_base
28+ pub bases : Vec < PyClassRef > , // tp_bases
2829 pub mro : Vec < PyClassRef > ,
2930 pub subclasses : RefCell < Vec < PyWeak > > ,
3031 pub attributes : RefCell < PyAttributes > ,
31- pub slots : RefCell < PyClassSlots > ,
32+ pub slots : RefCell < PyClassSlot > ,
3233}
3334
3435impl fmt:: Display for PyClass {
@@ -491,7 +492,7 @@ fn linearise_mro(mut bases: Vec<Vec<PyClassRef>>) -> Option<Vec<PyClassRef>> {
491492pub fn new (
492493 typ : PyClassRef ,
493494 name : & str ,
494- _base : PyClassRef ,
495+ base : PyClassRef ,
495496 bases : Vec < PyClassRef > ,
496497 dict : HashMap < String , PyObjectRef > ,
497498) -> PyResult < PyClassRef > {
@@ -500,6 +501,7 @@ pub fn new(
500501 let new_type = PyObject {
501502 payload : PyClass {
502503 name : String :: from ( name) ,
504+ base : Some ( base. clone ( ) ) ,
503505 bases,
504506 mro,
505507 subclasses : RefCell :: default ( ) ,
@@ -548,8 +550,8 @@ fn calculate_meta_class(
548550}
549551
550552fn best_base < ' a > ( bases : & ' a [ PyClassRef ] , vm : & VirtualMachine ) -> PyResult < PyClassRef > {
551- // let mut base = None;
552- // let mut winner = None;
553+ let mut base = None ;
554+ let mut winner = None ;
553555
554556 for base_i in bases {
555557 // base_proto = PyTuple_GET_ITEM(bases, i);
@@ -571,28 +573,41 @@ fn best_base<'a>(bases: &'a [PyClassRef], vm: &VirtualMachine) -> PyResult<PyCla
571573 base_i. name
572574 ) ) ) ;
573575 }
574- // candidate = solid_base(base_i);
575- // if (winner == NULL) {
576- // winner = candidate;
577- // base = base_i;
578- // }
579- // else if (PyType_IsSubtype(winner, candidate))
580- // ;
581- // else if (PyType_IsSubtype(candidate, winner)) {
582- // winner = candidate;
583- // base = base_i;
584- // }
585- // else {
586- // PyErr_SetString(
587- // PyExc_TypeError,
588- // "multiple bases have "
589- // "instance lay-out conflict");
590- // return NULL;
591- // }
576+ let candidate = solid_base ( base_i, vm) ;
577+ if winner. is_none ( ) {
578+ winner = Some ( candidate) ;
579+ base = Some ( base_i) ;
580+ } else if issubclass ( winner. unwrap ( ) , candidate) {
581+ } else if issubclass ( candidate, winner. unwrap ( ) ) {
582+ winner = Some ( candidate) ;
583+ base = Some ( base_i) ;
584+ } else {
585+ return Err (
586+ vm. new_type_error ( "multiple bases have instance lay-out conflict" . to_owned ( ) )
587+ ) ;
588+ }
592589 }
593590
594- // FIXME: Ok(base.unwrap()) is expected
595- Ok ( bases[ 0 ] . clone ( ) )
591+ Ok ( base. unwrap ( ) . clone ( ) )
592+ }
593+
594+ fn extra_ivars ( _typ : & PyClassRef , _base : & PyClassRef ) -> bool {
595+ // TODO
596+ true
597+ }
598+
599+ fn solid_base < ' a > ( typ : & ' a PyClassRef , vm : & ' a VirtualMachine ) -> & ' a PyClassRef {
600+ let base = if let Some ( ref tp_base) = typ. base {
601+ solid_base ( tp_base, vm)
602+ } else {
603+ & vm. ctx . types . type_type
604+ } ;
605+
606+ if extra_ivars ( typ, base) {
607+ typ
608+ } else {
609+ base
610+ }
596611}
597612
598613#[ cfg( test) ]
0 commit comments