1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use crate::obj::objproperty::PyPropertyRef;
use crate::obj::objstr::PyStringRef;
use crate::obj::objtype::{class_get_attr, class_has_attr, PyClassRef};
use crate::pyobject::{
IntoPyObject, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol,
};
use crate::vm::VirtualMachine;
#[derive(Debug)]
pub struct PyNone;
pub type PyNoneRef = PyRef<PyNone>;
impl PyValue for PyNone {
fn class(vm: &VirtualMachine) -> PyClassRef {
vm.ctx.none().class()
}
}
impl IntoPyObject for () {
fn into_pyobject(self, vm: &VirtualMachine) -> PyResult {
Ok(vm.ctx.none())
}
}
impl<T: IntoPyObject> IntoPyObject for Option<T> {
fn into_pyobject(self, vm: &VirtualMachine) -> PyResult {
match self {
Some(x) => x.into_pyobject(vm),
None => Ok(vm.ctx.none()),
}
}
}
impl PyNoneRef {
fn repr(self, _vm: &VirtualMachine) -> PyResult<String> {
Ok("None".to_string())
}
fn bool(self, _vm: &VirtualMachine) -> PyResult<bool> {
Ok(false)
}
fn get_attribute(self, name: PyStringRef, vm: &VirtualMachine) -> PyResult {
vm_trace!("None.__getattribute__({:?}, {:?})", self, name);
let cls = self.class();
fn call_descriptor(
descriptor: PyObjectRef,
get_func: PyObjectRef,
obj: PyObjectRef,
cls: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult {
if let Ok(property) = PyPropertyRef::try_from_object(vm, descriptor.clone()) {
property.instance_binding_get(obj, vm)
} else {
vm.invoke(&get_func, vec![descriptor, obj, cls])
}
}
if let Some(attr) = class_get_attr(&cls, name.as_str()) {
let attr_class = attr.class();
if class_has_attr(&attr_class, "__set__") {
if let Some(get_func) = class_get_attr(&attr_class, "__get__") {
return call_descriptor(
attr,
get_func,
self.into_object(),
cls.into_object(),
vm,
);
}
}
}
if let Some(attr) = class_get_attr(&cls, name.as_str()) {
let attr_class = attr.class();
if let Some(get_func) = class_get_attr(&attr_class, "__get__") {
call_descriptor(attr, get_func, self.into_object(), cls.into_object(), vm)
} else {
Ok(attr)
}
} else if let Some(getter) = class_get_attr(&cls, "__getattr__") {
vm.invoke(&getter, vec![self.into_object(), name.into_object()])
} else {
Err(vm.new_attribute_error(format!("{} has no attribute '{}'", self.as_object(), name)))
}
}
}
fn none_new(_: PyClassRef, vm: &VirtualMachine) -> PyNoneRef {
vm.ctx.none.clone()
}
pub fn init(context: &PyContext) {
extend_class!(context, &context.none.class(), {
"__new__" => context.new_rustfunc(none_new),
"__repr__" => context.new_rustfunc(PyNoneRef::repr),
"__bool__" => context.new_rustfunc(PyNoneRef::bool),
"__getattribute__" => context.new_rustfunc(PyNoneRef::get_attribute)
});
}