Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
9 changes: 9 additions & 0 deletions tests/snippets/types_snippet.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,14 @@
assert type(cls) is metaclass
assert type(metaclass) is type

assert issubclass(metaclass, type)
assert isinstance(cls, type)

assert inst.__class__ is cls
assert cls.__class__ is metaclass
assert metaclass.__class__ is type
assert type.__class__ is type
assert None.__class__ is type(None)

assert isinstance(type, type)
assert issubclass(type, type)
34 changes: 34 additions & 0 deletions vm/src/obj/objfunction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ pub fn init(context: &PyContext) {
context.new_rustfunc(member_get),
);

let data_descriptor_type = &context.data_descriptor_type;
context.set_attr(
&data_descriptor_type,
"__get__",
context.new_rustfunc(data_get),
);
context.set_attr(
&data_descriptor_type,
"__set__",
context.new_rustfunc(data_set),
);

let classmethod_type = &context.classmethod_type;
context.set_attr(
&classmethod_type,
Expand Down Expand Up @@ -83,6 +95,28 @@ fn member_get(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
}
}

fn data_get(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
match args.shift().get_attr("fget") {
Some(function) => vm.invoke(function, args),
None => {
println!("A");
Comment thread
BenLewis-Seequent marked this conversation as resolved.
Outdated
let attribute_error = vm.context().exceptions.attribute_error.clone();
Err(vm.new_exception(attribute_error, String::from("Attribute Error")))
}
}
}

fn data_set(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
match args.shift().get_attr("fset") {
Some(function) => vm.invoke(function, args),
None => {
println!("B");
let attribute_error = vm.context().exceptions.attribute_error.clone();
Err(vm.new_exception(attribute_error, String::from("Attribute Error")))
}
}
}

// Classmethod type methods:
fn classmethod_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
trace!("classmethod.__get__ {:?}", args.args);
Expand Down
18 changes: 18 additions & 0 deletions vm/src/obj/objobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ pub fn init(context: &PyContext) {

context.set_attr(&object, "__new__", context.new_rustfunc(new_instance));
context.set_attr(&object, "__init__", context.new_rustfunc(object_init));
context.set_attr(
&object,
"__class__",
context.new_data_descriptor(object_class, object_class_setter),
);
context.set_attr(&object, "__eq__", context.new_rustfunc(object_eq));
context.set_attr(&object, "__ne__", context.new_rustfunc(object_ne));
context.set_attr(&object, "__lt__", context.new_rustfunc(object_lt));
Expand Down Expand Up @@ -190,6 +195,19 @@ fn object_init(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult {
Ok(vm.ctx.none())
}

fn object_class(_obj: PyObjectRef, owner: PyObjectRef, _vm: &mut VirtualMachine) -> PyObjectRef {
Comment thread
BenLewis-Seequent marked this conversation as resolved.
owner
}

fn object_class_setter(
instance: PyObjectRef,
_value: PyObjectRef,
vm: &mut VirtualMachine,
) -> PyResult {
let type_repr = vm.to_pystr(&instance.typ())?;
Err(vm.new_type_error(format!("can't change class of type '{}'", type_repr)))
}

fn object_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
match args.args[0].payload {
PyObjectPayload::Class { ref dict, .. } | PyObjectPayload::Instance { ref dict, .. } => {
Expand Down
5 changes: 0 additions & 5 deletions vm/src/obj/objtype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,6 @@ pub fn init(context: &PyContext) {
"__mro__",
context.new_member_descriptor(type_mro),
);
context.set_attr(
&type_type,
"__class__",
context.new_member_descriptor(type_new),
);
context.set_attr(&type_type, "__repr__", context.new_rustfunc(type_repr));
context.set_attr(
&type_type,
Expand Down
24 changes: 24 additions & 0 deletions vm/src/pyobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ pub struct PyContext {
pub module_type: PyObjectRef,
pub bound_method_type: PyObjectRef,
pub member_descriptor_type: PyObjectRef,
pub data_descriptor_type: PyObjectRef,
pub object: PyObjectRef,
pub exceptions: exceptions::ExceptionZoo,
}
Expand Down Expand Up @@ -199,6 +200,8 @@ impl PyContext {
let bound_method_type = create_type("method", &type_type, &object_type, &dict_type);
let member_descriptor_type =
create_type("member_descriptor", &type_type, &object_type, &dict_type);
let data_descriptor_type =
create_type("data_descriptor", &type_type, &object_type, &dict_type);
let str_type = create_type("str", &type_type, &object_type, &dict_type);
let list_type = create_type("list", &type_type, &object_type, &dict_type);
let set_type = create_type("set", &type_type, &object_type, &dict_type);
Expand Down Expand Up @@ -285,6 +288,7 @@ impl PyContext {
module_type,
bound_method_type,
member_descriptor_type,
data_descriptor_type,
type_type,
exceptions,
};
Expand Down Expand Up @@ -449,6 +453,10 @@ impl PyContext {
pub fn member_descriptor_type(&self) -> PyObjectRef {
self.member_descriptor_type.clone()
}
pub fn data_descriptor_type(&self) -> PyObjectRef {
self.data_descriptor_type.clone()
}

pub fn type_type(&self) -> PyObjectRef {
self.type_type.clone()
}
Expand Down Expand Up @@ -658,6 +666,22 @@ impl PyContext {
self.new_instance(self.member_descriptor_type(), Some(dict))
}

pub fn new_data_descriptor<
G: IntoPyNativeFunc<(I, PyObjectRef), T>,
S: IntoPyNativeFunc<(I, T), PyResult>,
T,
I,
>(
&self,
getter: G,
setter: S,
) -> PyObjectRef {
let mut dict = PyAttributes::new();
dict.insert("fget".to_string(), self.new_rustfunc(getter));
dict.insert("fset".to_string(), self.new_rustfunc(setter));
self.new_instance(self.data_descriptor_type(), Some(dict))
}

pub fn new_instance(&self, class: PyObjectRef, dict: Option<PyAttributes>) -> PyObjectRef {
let dict = if let Some(dict) = dict {
dict
Expand Down