@@ -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 {
@@ -361,6 +362,22 @@ pub fn issubclass(subclass: &PyClassRef, cls: &PyClassRef) -> bool {
361362 subclass. is ( cls) || mro. iter ( ) . any ( |c| c. is ( cls. as_object ( ) ) )
362363}
363364
365+ pub fn is_subtype_base_chain ( subclass : & PyClassRef , cls : & PyClassRef ) -> bool {
366+ let mut a = subclass;
367+ loop {
368+ if subclass. is ( cls) {
369+ return true ;
370+ } else {
371+ if let Some ( ref base) = a. base {
372+ a = base;
373+ } else {
374+ break ;
375+ }
376+ }
377+ }
378+ cls. base . is_none ( )
379+ }
380+
364381pub fn type_new (
365382 zelf : PyClassRef ,
366383 cls : PyClassRef ,
@@ -491,7 +508,7 @@ fn linearise_mro(mut bases: Vec<Vec<PyClassRef>>) -> Option<Vec<PyClassRef>> {
491508pub fn new (
492509 typ : PyClassRef ,
493510 name : & str ,
494- _base : PyClassRef ,
511+ base : PyClassRef ,
495512 bases : Vec < PyClassRef > ,
496513 dict : HashMap < String , PyObjectRef > ,
497514) -> PyResult < PyClassRef > {
@@ -500,6 +517,7 @@ pub fn new(
500517 let new_type = PyObject {
501518 payload : PyClass {
502519 name : String :: from ( name) ,
520+ base : Some ( base. clone ( ) ) ,
503521 bases,
504522 mro,
505523 subclasses : RefCell :: default ( ) ,
@@ -548,8 +566,8 @@ fn calculate_meta_class(
548566}
549567
550568fn best_base < ' a > ( bases : & ' a [ PyClassRef ] , vm : & VirtualMachine ) -> PyResult < PyClassRef > {
551- // let mut base = None;
552- // let mut winner = None;
569+ let mut base = None ;
570+ let mut winner = None ;
553571
554572 for base_i in bases {
555573 // base_proto = PyTuple_GET_ITEM(bases, i);
@@ -571,28 +589,41 @@ fn best_base<'a>(bases: &'a [PyClassRef], vm: &VirtualMachine) -> PyResult<PyCla
571589 base_i. name
572590 ) ) ) ;
573591 }
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- // }
592+ let candidate = solid_base ( base_i, vm) ;
593+ if winner. is_none ( ) {
594+ winner = Some ( candidate) ;
595+ base = Some ( base_i) ;
596+ } else if issubclass ( winner. unwrap ( ) , candidate) {
597+ } else if issubclass ( candidate, winner. unwrap ( ) ) {
598+ winner = Some ( candidate) ;
599+ base = Some ( base_i) ;
600+ } else {
601+ return Err (
602+ vm. new_type_error ( "multiple bases have instance lay-out conflict" . to_owned ( ) )
603+ ) ;
604+ }
592605 }
593606
594- // FIXME: Ok(base.unwrap()) is expected
595- Ok ( bases[ 0 ] . clone ( ) )
607+ Ok ( base. unwrap ( ) . clone ( ) )
608+ }
609+
610+ fn extra_ivars ( _typ : & PyClassRef , _base : & PyClassRef ) -> bool {
611+ // TODO
612+ false
613+ }
614+
615+ fn solid_base < ' a > ( typ : & ' a PyClassRef , vm : & ' a VirtualMachine ) -> & ' a PyClassRef {
616+ let base = if let Some ( ref tp_base) = typ. base {
617+ solid_base ( tp_base, vm)
618+ } else {
619+ & vm. ctx . types . type_type
620+ } ;
621+
622+ if extra_ivars ( typ, base) {
623+ typ
624+ } else {
625+ base
626+ }
596627}
597628
598629#[ cfg( test) ]
0 commit comments