Skip to content

Commit c186d69

Browse files
committed
tp_base and better implementation for best_base
1 parent 7cdaba7 commit c186d69

File tree

3 files changed

+48
-29
lines changed

3 files changed

+48
-29
lines changed

vm/src/obj/objtype.rs

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -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};
1818
use crate::vm::VirtualMachine;
1919

2020
/// type(object_or_name, bases, dict)
@@ -24,11 +24,12 @@ use crate::vm::VirtualMachine;
2424
#[derive(Debug)]
2525
pub 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

3435
impl fmt::Display for PyClass {
@@ -491,7 +492,7 @@ fn linearise_mro(mut bases: Vec<Vec<PyClassRef>>) -> Option<Vec<PyClassRef>> {
491492
pub 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

550552
fn 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)]

vm/src/slots.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,16 @@ impl Default for PyTpFlags {
2424
}
2525

2626
#[derive(Default)]
27-
pub struct PyClassSlots {
27+
pub struct PyClassSlot {
2828
pub flags: PyTpFlags,
2929
pub new: Option<PyNativeFunc>,
3030
pub call: Option<PyNativeFunc>,
3131
pub descr_get: Option<PyNativeFunc>,
3232
}
3333

34-
impl std::fmt::Debug for PyClassSlots {
34+
impl std::fmt::Debug for PyClassSlot {
3535
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36-
f.write_str("PyClassSlots")
36+
f.write_str("PyClassSlot")
3737
}
3838
}
3939

vm/src/types.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ fn init_type_hierarchy() -> (PyClassRef, PyClassRef) {
279279
dict: None,
280280
payload: PyClass {
281281
name: String::from("type"),
282+
base: None,
282283
bases: vec![],
283284
mro: vec![],
284285
subclasses: RefCell::default(),
@@ -293,6 +294,7 @@ fn init_type_hierarchy() -> (PyClassRef, PyClassRef) {
293294
dict: None,
294295
payload: PyClass {
295296
name: String::from("object"),
297+
base: None,
296298
bases: vec![],
297299
mro: vec![],
298300
subclasses: RefCell::default(),
@@ -319,6 +321,7 @@ fn init_type_hierarchy() -> (PyClassRef, PyClassRef) {
319321
// dummy PyClass
320322
let cls = PyClass {
321323
name: Default::default(),
324+
base: Default::default(),
322325
bases: Default::default(),
323326
mro: Default::default(),
324327
subclasses: Default::default(),
@@ -348,6 +351,7 @@ fn init_type_hierarchy() -> (PyClassRef, PyClassRef) {
348351
let object_type = PyClassRef::new_ref_unchecked(Rc::from_raw(object_type_ptr));
349352

350353
(*type_type_ptr).payload.mro = vec![object_type.clone()];
354+
(*type_type_ptr).payload.base = Some(object_type.clone());
351355
(*type_type_ptr).payload.bases = vec![object_type.clone()];
352356

353357
(type_type, object_type)

0 commit comments

Comments
 (0)