diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index d8ddb06f70..8331454f6c 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -14,7 +14,7 @@ use crate::pyobject::{ IdProtocol, PyAttributes, PyClassImpl, PyContext, PyIterable, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, }; -use crate::slots::{PyClassSlots, PyTpFlags}; +use crate::slots::{PyClassSlot, PyTpFlags}; use crate::vm::VirtualMachine; /// type(object_or_name, bases, dict) @@ -24,11 +24,12 @@ use crate::vm::VirtualMachine; #[derive(Debug)] pub struct PyClass { pub name: String, - pub bases: Vec, + pub base: Option, // tp_base + pub bases: Vec, // tp_bases pub mro: Vec, pub subclasses: RefCell>, pub attributes: RefCell, - pub slots: RefCell, + pub slots: RefCell, } impl fmt::Display for PyClass { @@ -361,6 +362,22 @@ pub fn issubclass(subclass: &PyClassRef, cls: &PyClassRef) -> bool { subclass.is(cls) || mro.iter().any(|c| c.is(cls.as_object())) } +pub fn is_subtype_base_chain(subclass: &PyClassRef, cls: &PyClassRef) -> bool { + let mut a = subclass; + loop { + if subclass.is(cls) { + return true; + } else { + if let Some(ref base) = a.base { + a = base; + } else { + break; + } + } + } + cls.base.is_none() +} + pub fn type_new( zelf: PyClassRef, cls: PyClassRef, @@ -491,7 +508,7 @@ fn linearise_mro(mut bases: Vec>) -> Option> { pub fn new( typ: PyClassRef, name: &str, - _base: PyClassRef, + base: PyClassRef, bases: Vec, dict: HashMap, ) -> PyResult { @@ -500,6 +517,7 @@ pub fn new( let new_type = PyObject { payload: PyClass { name: String::from(name), + base: Some(base.clone()), bases, mro, subclasses: RefCell::default(), @@ -548,8 +566,8 @@ fn calculate_meta_class( } fn best_base<'a>(bases: &'a [PyClassRef], vm: &VirtualMachine) -> PyResult { - // let mut base = None; - // let mut winner = None; + let mut base = None; + let mut winner = None; for base_i in bases { // base_proto = PyTuple_GET_ITEM(bases, i); @@ -571,28 +589,41 @@ fn best_base<'a>(bases: &'a [PyClassRef], vm: &VirtualMachine) -> PyResult bool { + // TODO + false +} + +fn solid_base<'a>(typ: &'a PyClassRef, vm: &'a VirtualMachine) -> &'a PyClassRef { + let base = if let Some(ref tp_base) = typ.base { + solid_base(tp_base, vm) + } else { + &vm.ctx.types.type_type + }; + + if extra_ivars(typ, base) { + typ + } else { + base + } } #[cfg(test)] diff --git a/vm/src/slots.rs b/vm/src/slots.rs index 818a1b974b..a100818a85 100644 --- a/vm/src/slots.rs +++ b/vm/src/slots.rs @@ -24,16 +24,16 @@ impl Default for PyTpFlags { } #[derive(Default)] -pub struct PyClassSlots { +pub struct PyClassSlot { pub flags: PyTpFlags, pub new: Option, pub call: Option, pub descr_get: Option, } -impl std::fmt::Debug for PyClassSlots { +impl std::fmt::Debug for PyClassSlot { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("PyClassSlots") + f.write_str("PyClassSlot") } } diff --git a/vm/src/types.rs b/vm/src/types.rs index 2c9d940265..bbf24f6aea 100644 --- a/vm/src/types.rs +++ b/vm/src/types.rs @@ -279,6 +279,7 @@ fn init_type_hierarchy() -> (PyClassRef, PyClassRef) { dict: None, payload: PyClass { name: String::from("type"), + base: None, bases: vec![], mro: vec![], subclasses: RefCell::default(), @@ -293,6 +294,7 @@ fn init_type_hierarchy() -> (PyClassRef, PyClassRef) { dict: None, payload: PyClass { name: String::from("object"), + base: None, bases: vec![], mro: vec![], subclasses: RefCell::default(), @@ -319,6 +321,7 @@ fn init_type_hierarchy() -> (PyClassRef, PyClassRef) { // dummy PyClass let cls = PyClass { name: Default::default(), + base: Default::default(), bases: Default::default(), mro: Default::default(), subclasses: Default::default(), @@ -348,6 +351,7 @@ fn init_type_hierarchy() -> (PyClassRef, PyClassRef) { let object_type = PyClassRef::new_ref_unchecked(Rc::from_raw(object_type_ptr)); (*type_type_ptr).payload.mro = vec![object_type.clone()]; + (*type_type_ptr).payload.base = Some(object_type.clone()); (*type_type_ptr).payload.bases = vec![object_type.clone()]; (type_type, object_type)