Skip to content

Add PyClass. #625

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions vm/src/obj/objdict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,11 +340,13 @@ pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, dict_type:
// this is not ideal
let ptr = PyObjectRef::into_raw(dict_type.clone()) as *mut PyObject;
unsafe {
(*ptr).payload = PyObjectPayload::Class {
name: String::from("dict"),
dict: RefCell::new(HashMap::new()),
mro: vec![object_type],
(*ptr).payload = PyObjectPayload::AnyRustValue {
value: Box::new(objtype::PyClass {
name: String::from("dict"),
mro: vec![object_type],
}),
};
(*ptr).dict = Some(RefCell::new(HashMap::new()));
(*ptr).typ = Some(type_type.clone());
}
}
Expand Down
38 changes: 22 additions & 16 deletions vm/src/obj/objobject.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::objstr;
use super::objtype;
use crate::function::PyRef;
use crate::pyobject::{
AttributeProtocol, DictProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject,
PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
Expand All @@ -8,6 +9,10 @@ use crate::vm::VirtualMachine;
use std::cell::RefCell;
use std::collections::HashMap;

#[derive(Clone, Debug)]
pub struct PyInstance;
pub type PyInstanceRef = PyRef<PyInstance>;

pub fn new_instance(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
// more or less __new__ operator
let type_ref = args.shift();
Expand All @@ -19,11 +24,13 @@ pub fn create_object(type_type: PyObjectRef, object_type: PyObjectRef, _dict_typ
// this is not ideal
let ptr = PyObjectRef::into_raw(object_type.clone()) as *mut PyObject;
unsafe {
(*ptr).payload = PyObjectPayload::Class {
name: String::from("object"),
dict: RefCell::new(HashMap::new()),
mro: vec![],
(*ptr).payload = PyObjectPayload::AnyRustValue {
value: Box::new(objtype::PyClass {
name: String::from("object"),
mro: vec![],
}),
};
(*ptr).dict = Some(RefCell::new(HashMap::new()));
(*ptr).typ = Some(type_type.clone());
}
}
Expand Down Expand Up @@ -105,13 +112,13 @@ fn object_delattr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
]
);

match zelf.payload {
PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => {
match zelf.dict {
Some(ref dict) => {
let attr_name = objstr::get_value(attr);
dict.borrow_mut().remove(&attr_name);
Ok(vm.get_none())
}
_ => Err(vm.new_type_error("TypeError: no dictionary.".to_string())),
None => Err(vm.new_type_error("TypeError: no dictionary.".to_string())),
}
}

Expand Down Expand Up @@ -210,15 +217,14 @@ fn object_class_setter(
}

fn object_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
match args.args[0].payload {
PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => {
let new_dict = vm.new_dict();
for (attr, value) in dict.borrow().iter() {
new_dict.set_item(&vm.ctx, &attr, value.clone());
}
Ok(new_dict)
if let Some(ref dict) = args.args[0].dict {
let new_dict = vm.new_dict();
for (attr, value) in dict.borrow().iter() {
new_dict.set_item(&vm.ctx, &attr, value.clone());
}
_ => Err(vm.new_type_error("TypeError: no dictionary.".to_string())),
Ok(new_dict)
} else {
Err(vm.new_type_error("TypeError: no dictionary.".to_string()))
}
}

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

// Get instance attributes:
if let PyObjectPayload::Instance { dict } = &obj.payload {
if let Some(dict) = &obj.dict {
for (name, value) in dict.borrow().iter() {
attributes.insert(name.to_string(), value.clone());
}
Expand Down
60 changes: 39 additions & 21 deletions vm/src/obj/objtype.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
use super::objdict;
use super::objstr;
use crate::function::PyRef;
use crate::pyobject::{
AttributeProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject, PyObjectPayload,
PyObjectRef, PyResult, TypeProtocol,
PyObjectPayload2, PyObjectRef, PyResult, TypeProtocol,
};
use crate::vm::VirtualMachine;
use std::cell::RefCell;
use std::collections::HashMap;

#[derive(Clone, Debug)]
pub struct PyClass {
pub name: String,
pub mro: Vec<PyObjectRef>,
}
pub type PyClassRef = PyRef<PyClass>;

impl PyObjectPayload2 for PyClass {
fn required_type(ctx: &PyContext) -> PyObjectRef {
ctx.type_type()
}
}

/*
* The magical type type
*/
Expand All @@ -16,11 +30,13 @@ pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, _dict_type:
// this is not ideal
let ptr = PyObjectRef::into_raw(type_type.clone()) as *mut PyObject;
unsafe {
(*ptr).payload = PyObjectPayload::Class {
name: String::from("type"),
dict: RefCell::new(PyAttributes::new()),
mro: vec![object_type],
(*ptr).payload = PyObjectPayload::AnyRustValue {
value: Box::new(PyClass {
name: String::from("type"),
mro: vec![object_type],
}),
};
(*ptr).dict = Some(RefCell::new(PyAttributes::new()));
(*ptr).typ = Some(type_type);
}
}
Expand Down Expand Up @@ -80,13 +96,12 @@ fn type_mro(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}

fn _mro(cls: PyObjectRef) -> Option<Vec<PyObjectRef>> {
match cls.payload {
PyObjectPayload::Class { ref mro, .. } => {
let mut mro = mro.clone();
mro.insert(0, cls.clone());
Some(mro)
}
_ => None,
if let Some(PyClass { ref mro, .. }) = cls.payload::<PyClass>() {
let mut mro = mro.clone();
mro.insert(0, cls.clone());
Some(mro)
} else {
None
}
}

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

pub fn get_type_name(typ: &PyObjectRef) -> String {
if let PyObjectPayload::Class { name, .. } = &typ.payload {
if let Some(PyClass { name, .. }) = &typ.payload::<PyClass>() {
name.clone()
} else {
panic!("Cannot get type_name of non-type type {:?}", typ);
Expand Down Expand Up @@ -248,7 +263,7 @@ pub fn get_attributes(obj: &PyObjectRef) -> PyAttributes {
let mut base_classes = _mro(obj.clone()).expect("Type get_attributes on non-type");
base_classes.reverse();
for bc in base_classes {
if let PyObjectPayload::Class { dict, .. } = &bc.payload {
if let Some(ref dict) = &bc.dict {
for (name, value) in dict.borrow().iter() {
attributes.insert(name.to_string(), value.clone());
}
Expand Down Expand Up @@ -313,14 +328,17 @@ pub fn new(
) -> PyResult {
let mros = bases.into_iter().map(|x| _mro(x).unwrap()).collect();
let mro = linearise_mro(mros).unwrap();
Ok(PyObject::new(
PyObjectPayload::Class {
name: String::from(name),
dict: RefCell::new(dict),
mro,
Ok(PyObject {
payload: PyObjectPayload::AnyRustValue {
value: Box::new(PyClass {
name: String::from(name),
mro,
}),
},
typ,
))
dict: Some(RefCell::new(dict)),
typ: Some(typ),
}
.into_ref())
}

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