Skip to content

Commit 0febcb9

Browse files
authored
Merge pull request RustPython#625 from RustPython/py_class
Add PyClass.
2 parents 50de085 + 21382fa commit 0febcb9

File tree

5 files changed

+142
-111
lines changed

5 files changed

+142
-111
lines changed

vm/src/obj/objdict.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -340,11 +340,13 @@ pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, dict_type:
340340
// this is not ideal
341341
let ptr = PyObjectRef::into_raw(dict_type.clone()) as *mut PyObject;
342342
unsafe {
343-
(*ptr).payload = PyObjectPayload::Class {
344-
name: String::from("dict"),
345-
dict: RefCell::new(HashMap::new()),
346-
mro: vec![object_type],
343+
(*ptr).payload = PyObjectPayload::AnyRustValue {
344+
value: Box::new(objtype::PyClass {
345+
name: String::from("dict"),
346+
mro: vec![object_type],
347+
}),
347348
};
349+
(*ptr).dict = Some(RefCell::new(HashMap::new()));
348350
(*ptr).typ = Some(type_type.clone());
349351
}
350352
}

vm/src/obj/objobject.rs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::objstr;
22
use super::objtype;
3+
use crate::function::PyRef;
34
use crate::pyobject::{
45
AttributeProtocol, DictProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject,
56
PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
@@ -8,6 +9,10 @@ use crate::vm::VirtualMachine;
89
use std::cell::RefCell;
910
use std::collections::HashMap;
1011

12+
#[derive(Clone, Debug)]
13+
pub struct PyInstance;
14+
pub type PyInstanceRef = PyRef<PyInstance>;
15+
1116
pub fn new_instance(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
1217
// more or less __new__ operator
1318
let type_ref = args.shift();
@@ -19,11 +24,13 @@ pub fn create_object(type_type: PyObjectRef, object_type: PyObjectRef, _dict_typ
1924
// this is not ideal
2025
let ptr = PyObjectRef::into_raw(object_type.clone()) as *mut PyObject;
2126
unsafe {
22-
(*ptr).payload = PyObjectPayload::Class {
23-
name: String::from("object"),
24-
dict: RefCell::new(HashMap::new()),
25-
mro: vec![],
27+
(*ptr).payload = PyObjectPayload::AnyRustValue {
28+
value: Box::new(objtype::PyClass {
29+
name: String::from("object"),
30+
mro: vec![],
31+
}),
2632
};
33+
(*ptr).dict = Some(RefCell::new(HashMap::new()));
2734
(*ptr).typ = Some(type_type.clone());
2835
}
2936
}
@@ -105,13 +112,13 @@ fn object_delattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
105112
]
106113
);
107114

108-
match zelf.payload {
109-
PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => {
115+
match zelf.dict {
116+
Some(ref dict) => {
110117
let attr_name = objstr::get_value(attr);
111118
dict.borrow_mut().remove(&attr_name);
112119
Ok(vm.get_none())
113120
}
114-
_ => Err(vm.new_type_error("TypeError: no dictionary.".to_string())),
121+
None => Err(vm.new_type_error("TypeError: no dictionary.".to_string())),
115122
}
116123
}
117124

@@ -210,15 +217,14 @@ fn object_class_setter(
210217
}
211218

212219
fn object_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
213-
match args.args[0].payload {
214-
PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => {
215-
let new_dict = vm.new_dict();
216-
for (attr, value) in dict.borrow().iter() {
217-
new_dict.set_item(&vm.ctx, &attr, value.clone());
218-
}
219-
Ok(new_dict)
220+
if let Some(ref dict) = args.args[0].dict {
221+
let new_dict = vm.new_dict();
222+
for (attr, value) in dict.borrow().iter() {
223+
new_dict.set_item(&vm.ctx, &attr, value.clone());
220224
}
221-
_ => Err(vm.new_type_error("TypeError: no dictionary.".to_string())),
225+
Ok(new_dict)
226+
} else {
227+
Err(vm.new_type_error("TypeError: no dictionary.".to_string()))
222228
}
223229
}
224230

@@ -264,7 +270,7 @@ pub fn get_attributes(obj: &PyObjectRef) -> PyAttributes {
264270
let mut attributes = objtype::get_attributes(&obj.typ());
265271

266272
// Get instance attributes:
267-
if let PyObjectPayload::Instance { dict } = &obj.payload {
273+
if let Some(dict) = &obj.dict {
268274
for (name, value) in dict.borrow().iter() {
269275
attributes.insert(name.to_string(), value.clone());
270276
}

vm/src/obj/objtype.rs

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
11
use super::objdict;
22
use super::objstr;
3+
use crate::function::PyRef;
34
use crate::pyobject::{
45
AttributeProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectPayload,
5-
PyObjectRef, PyResult, TypeProtocol,
6+
PyObjectPayload2, PyObjectRef, PyResult, TypeProtocol,
67
};
78
use crate::vm::VirtualMachine;
89
use std::cell::RefCell;
910
use std::collections::HashMap;
1011

12+
#[derive(Clone, Debug)]
13+
pub struct PyClass {
14+
pub name: String,
15+
pub mro: Vec<PyObjectRef>,
16+
}
17+
pub type PyClassRef = PyRef<PyClass>;
18+
19+
impl PyObjectPayload2 for PyClass {
20+
fn required_type(ctx: &PyContext) -> PyObjectRef {
21+
ctx.type_type()
22+
}
23+
}
24+
1125
/*
1226
* The magical type type
1327
*/
@@ -16,11 +30,13 @@ pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, _dict_type:
1630
// this is not ideal
1731
let ptr = PyObjectRef::into_raw(type_type.clone()) as *mut PyObject;
1832
unsafe {
19-
(*ptr).payload = PyObjectPayload::Class {
20-
name: String::from("type"),
21-
dict: RefCell::new(PyAttributes::new()),
22-
mro: vec![object_type],
33+
(*ptr).payload = PyObjectPayload::AnyRustValue {
34+
value: Box::new(PyClass {
35+
name: String::from("type"),
36+
mro: vec![object_type],
37+
}),
2338
};
39+
(*ptr).dict = Some(RefCell::new(PyAttributes::new()));
2440
(*ptr).typ = Some(type_type);
2541
}
2642
}
@@ -80,13 +96,12 @@ fn type_mro(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
8096
}
8197

8298
fn _mro(cls: PyObjectRef) -> Option<Vec<PyObjectRef>> {
83-
match cls.payload {
84-
PyObjectPayload::Class { ref mro, .. } => {
85-
let mut mro = mro.clone();
86-
mro.insert(0, cls.clone());
87-
Some(mro)
88-
}
89-
_ => None,
99+
if let Some(PyClass { ref mro, .. }) = cls.payload::<PyClass>() {
100+
let mut mro = mro.clone();
101+
mro.insert(0, cls.clone());
102+
Some(mro)
103+
} else {
104+
None
90105
}
91106
}
92107

@@ -127,7 +142,7 @@ fn type_subclass_check(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
127142
}
128143

129144
pub fn get_type_name(typ: &PyObjectRef) -> String {
130-
if let PyObjectPayload::Class { name, .. } = &typ.payload {
145+
if let Some(PyClass { name, .. }) = &typ.payload::<PyClass>() {
131146
name.clone()
132147
} else {
133148
panic!("Cannot get type_name of non-type type {:?}", typ);
@@ -248,7 +263,7 @@ pub fn get_attributes(obj: &PyObjectRef) -> PyAttributes {
248263
let mut base_classes = _mro(obj.clone()).expect("Type get_attributes on non-type");
249264
base_classes.reverse();
250265
for bc in base_classes {
251-
if let PyObjectPayload::Class { dict, .. } = &bc.payload {
266+
if let Some(ref dict) = &bc.dict {
252267
for (name, value) in dict.borrow().iter() {
253268
attributes.insert(name.to_string(), value.clone());
254269
}
@@ -313,14 +328,17 @@ pub fn new(
313328
) -> PyResult {
314329
let mros = bases.into_iter().map(|x| _mro(x).unwrap()).collect();
315330
let mro = linearise_mro(mros).unwrap();
316-
Ok(PyObject::new(
317-
PyObjectPayload::Class {
318-
name: String::from(name),
319-
dict: RefCell::new(dict),
320-
mro,
331+
Ok(PyObject {
332+
payload: PyObjectPayload::AnyRustValue {
333+
value: Box::new(PyClass {
334+
name: String::from(name),
335+
mro,
336+
}),
321337
},
322-
typ,
323-
))
338+
dict: Some(RefCell::new(dict)),
339+
typ: Some(typ),
340+
}
341+
.into_ref())
324342
}
325343

326344
fn type_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {

0 commit comments

Comments
 (0)