forked from Rust-related/RustPython
Implement object.__getattribute__.
This commit is contained in:
@@ -15,7 +15,7 @@ pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObje
|
||||
PyObjectKind::String { ref value } => !value.is_empty(),
|
||||
PyObjectKind::None { .. } => false,
|
||||
_ => {
|
||||
if let Ok(f) = objtype::get_attribute(vm, obj.clone(), &String::from("__bool__")) {
|
||||
if let Ok(f) = vm.get_attribute(obj.clone(), &String::from("__bool__")) {
|
||||
let bool_res = vm.invoke(f, PyFuncArgs::default())?;
|
||||
let v = match bool_res.borrow().kind {
|
||||
PyObjectKind::Integer { ref value } => !value.is_zero(),
|
||||
|
||||
@@ -5,6 +5,7 @@ use super::super::pyobject::{
|
||||
use super::super::vm::VirtualMachine;
|
||||
use super::objbool;
|
||||
use super::objdict;
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
|
||||
pub fn new_instance(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
|
||||
@@ -15,12 +16,6 @@ pub fn new_instance(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
|
||||
Ok(obj)
|
||||
}
|
||||
|
||||
pub fn call(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
|
||||
let instance = args.shift();
|
||||
let function = objtype::get_attribute(vm, instance, &String::from("__call__"))?;
|
||||
vm.invoke(function, args)
|
||||
}
|
||||
|
||||
pub fn create_object(type_type: PyObjectRef, object_type: PyObjectRef, dict_type: PyObjectRef) {
|
||||
(*object_type.borrow_mut()).kind = PyObjectKind::Class {
|
||||
name: String::from("object"),
|
||||
@@ -101,6 +96,10 @@ pub fn init(context: &PyContext) {
|
||||
object.set_attr("__hash__", context.new_rustfunc(object_hash));
|
||||
object.set_attr("__str__", context.new_rustfunc(object_str));
|
||||
object.set_attr("__repr__", context.new_rustfunc(object_repr));
|
||||
object.set_attr(
|
||||
"__getattribute__",
|
||||
context.new_rustfunc(object_getattribute),
|
||||
);
|
||||
}
|
||||
|
||||
fn object_init(vm: &mut VirtualMachine, _args: PyFuncArgs) -> PyResult {
|
||||
@@ -114,3 +113,65 @@ fn object_dict(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
_ => Err(vm.new_type_error("TypeError: no dictionary.".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
fn object_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(
|
||||
vm,
|
||||
args,
|
||||
required = [
|
||||
(obj, Some(vm.ctx.object())),
|
||||
(name_str, Some(vm.ctx.str_type()))
|
||||
]
|
||||
);
|
||||
let name = objstr::get_value(&name_str);
|
||||
trace!("object.__getattribute__({:?}, {:?})", obj, name);
|
||||
let cls = obj.typ();
|
||||
|
||||
if let Some(attr) = cls.get_attr(&name) {
|
||||
let attr_class = attr.typ();
|
||||
if attr_class.has_attr("__set__") {
|
||||
if let Some(descriptor) = attr_class.get_attr("__get__") {
|
||||
return vm.invoke(
|
||||
descriptor,
|
||||
PyFuncArgs {
|
||||
args: vec![attr, obj.clone(), cls],
|
||||
kwargs: vec![],
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(obj_attr) = obj.get_attr(&name) {
|
||||
Ok(obj_attr)
|
||||
} else if let Some(attr) = cls.get_attr(&name) {
|
||||
let attr_class = attr.typ();
|
||||
if let Some(descriptor) = attr_class.get_attr("__get__") {
|
||||
vm.invoke(
|
||||
descriptor,
|
||||
PyFuncArgs {
|
||||
args: vec![attr, obj.clone(), cls],
|
||||
kwargs: vec![],
|
||||
},
|
||||
)
|
||||
} else {
|
||||
Ok(attr)
|
||||
}
|
||||
} else {
|
||||
if let Some(getter) = cls.get_attr("__getattr__") {
|
||||
vm.invoke(
|
||||
getter,
|
||||
PyFuncArgs {
|
||||
args: vec![cls, name_str.clone()],
|
||||
kwargs: vec![],
|
||||
},
|
||||
)
|
||||
} else {
|
||||
let attribute_error = vm.context().exceptions.attribute_error.clone();
|
||||
Err(vm.new_exception(
|
||||
attribute_error,
|
||||
format!("{:?} object has no attribute {}", cls, name),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,34 +137,34 @@ pub fn type_call(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult {
|
||||
Ok(obj)
|
||||
}
|
||||
|
||||
pub fn get_attribute(vm: &mut VirtualMachine, obj: PyObjectRef, name: &str) -> PyResult {
|
||||
let cls = obj.typ();
|
||||
trace!("get_attribute: {:?}, {:?}, {:?}", cls, obj, name);
|
||||
if let Some(attr) = cls.get_attr(name) {
|
||||
let attr_class = attr.typ();
|
||||
if let Some(descriptor) = attr_class.get_attr("__get__") {
|
||||
return vm.invoke(
|
||||
descriptor,
|
||||
PyFuncArgs {
|
||||
args: vec![attr, obj, cls],
|
||||
kwargs: vec![],
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
// pub fn get_attribute(vm: &mut VirtualMachine, obj: PyObjectRef, name: &str) -> PyResult {
|
||||
// let cls = obj.typ();
|
||||
// trace!("get_attribute: {:?}, {:?}, {:?}", cls, obj, name);
|
||||
// if let Some(attr) = cls.get_attr(name) {
|
||||
// let attr_class = attr.typ();
|
||||
// if let Some(descriptor) = attr_class.get_attr("__get__") {
|
||||
// return vm.invoke(
|
||||
// descriptor,
|
||||
// PyFuncArgs {
|
||||
// args: vec![attr, obj, cls],
|
||||
// kwargs: vec![],
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
if let Some(obj_attr) = obj.get_attr(name) {
|
||||
Ok(obj_attr)
|
||||
} else if let Some(cls_attr) = cls.get_attr(name) {
|
||||
Ok(cls_attr)
|
||||
} else {
|
||||
let attribute_error = vm.context().exceptions.attribute_error.clone();
|
||||
Err(vm.new_exception(
|
||||
attribute_error,
|
||||
format!("{:?} object has no attribute {}", cls, name),
|
||||
))
|
||||
}
|
||||
}
|
||||
// if let Some(obj_attr) = obj.get_attr(name) {
|
||||
// Ok(obj_attr)
|
||||
// } else if let Some(cls_attr) = cls.get_attr(name) {
|
||||
// Ok(cls_attr)
|
||||
// } else {
|
||||
// let attribute_error = vm.context().exceptions.attribute_error.clone();
|
||||
// Err(vm.new_exception(
|
||||
// attribute_error,
|
||||
// format!("{:?} object has no attribute {}", cls, name),
|
||||
// ))
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn get_attributes(obj: &PyObjectRef) -> HashMap<String, PyObjectRef> {
|
||||
// Gather all members here:
|
||||
@@ -264,7 +264,7 @@ fn type_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
}
|
||||
|
||||
pub fn call(vm: &mut VirtualMachine, typ: PyObjectRef, args: PyFuncArgs) -> PyResult {
|
||||
let function = get_attribute(vm, typ, &String::from("__call__"))?;
|
||||
let function = vm.get_attribute(typ, &String::from("__call__"))?;
|
||||
vm.invoke(function, args)
|
||||
}
|
||||
|
||||
|
||||
29
vm/src/vm.rs
29
vm/src/vm.rs
@@ -17,7 +17,10 @@ use super::obj::objlist;
|
||||
use super::obj::objobject;
|
||||
use super::obj::objtuple;
|
||||
use super::obj::objtype;
|
||||
use super::pyobject::{DictProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult};
|
||||
use super::pyobject::{
|
||||
AttributeProtocol, DictProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
};
|
||||
use super::stdlib;
|
||||
use super::sysmodule;
|
||||
|
||||
@@ -174,12 +177,18 @@ impl VirtualMachine {
|
||||
name: _,
|
||||
dict: _,
|
||||
mro: _,
|
||||
} => objtype::call(self, func_ref.clone(), args),
|
||||
} => {
|
||||
let function = self.get_attribute(func_ref.clone(), "__call__")?;
|
||||
self.invoke(function, args)
|
||||
}
|
||||
PyObjectKind::BoundMethod {
|
||||
ref function,
|
||||
ref object,
|
||||
} => self.invoke(function.clone(), args.insert(object.clone())),
|
||||
PyObjectKind::Instance { .. } => objobject::call(self, args.insert(func_ref.clone())),
|
||||
PyObjectKind::Instance { .. } => {
|
||||
let function = self.get_attribute(func_ref.clone(), "__call__")?;
|
||||
self.invoke(function, args)
|
||||
}
|
||||
ref kind => {
|
||||
unimplemented!("invoke unimplemented for: {:?}", kind);
|
||||
}
|
||||
@@ -371,7 +380,19 @@ impl VirtualMachine {
|
||||
}
|
||||
|
||||
pub fn get_attribute(&mut self, obj: PyObjectRef, attr_name: &str) -> PyResult {
|
||||
objtype::get_attribute(self, obj.clone(), attr_name)
|
||||
let cls = obj.typ();
|
||||
if let Some(attr) = cls.get_attr("__getattribute__") {
|
||||
let name = self.new_str(attr_name.to_string());
|
||||
self.invoke(
|
||||
attr,
|
||||
PyFuncArgs {
|
||||
args: vec![obj.clone(), name],
|
||||
kwargs: vec![],
|
||||
},
|
||||
)
|
||||
} else {
|
||||
panic!("Everything should have a __getattribute__");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn _sub(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult {
|
||||
|
||||
Reference in New Issue
Block a user