forked from RustPython/RustPython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathobjsuper.rs
More file actions
86 lines (72 loc) · 2.68 KB
/
objsuper.rs
File metadata and controls
86 lines (72 loc) · 2.68 KB
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
/*! Python `super` class.
See also:
https://github.com/python/cpython/blob/50b48572d9a90c5bb36e2bef6179548ea927a35a/Objects/typeobject.c#L7663
*/
use super::objtype;
use crate::pyobject::{PyContext, PyFuncArgs, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
pub fn init(context: &PyContext) {
let super_type = &context.super_type;
let super_doc = "super() -> same as super(__class__, <first argument>)\n\
super(type) -> unbound super object\n\
super(type, obj) -> bound super object; requires isinstance(obj, type)\n\
super(type, type2) -> bound super object; requires issubclass(type2, type)\n\
Typical use to call a cooperative superclass method:\n\
class C(B):\n \
def meth(self, arg):\n \
super().meth(arg)\n\
This works for class methods too:\n\
class C(B):\n \
@classmethod\n \
def cmeth(cls, arg):\n \
super().cmeth(arg)\n";
context.set_attr(&super_type, "__init__", context.new_rustfunc(super_init));
context.set_attr(
&super_type,
"__doc__",
context.new_str(super_doc.to_string()),
);
}
fn super_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
trace!("super.__init__ {:?}", args.args);
arg_check!(
vm,
args,
required = [(inst, None)],
optional = [(py_type, None), (py_obj, None)]
);
// Get the type:
let py_type = if let Some(ty) = py_type {
ty.clone()
} else {
// TODO: implement complex logic here....
unimplemented!("TODO: get frame and determine instance and class?");
// let frame = vm.get_current_frame();
//
// vm.get_none()
};
// Check type argument:
if !objtype::isinstance(&py_type, &vm.get_type()) {
let type_name = objtype::get_type_name(&py_type.typ());
return Err(vm.new_type_error(format!(
"super() argument 1 must be type, not {}",
type_name
)));
}
// Get the bound object:
let py_obj = if let Some(obj) = py_obj {
obj.clone()
} else {
vm.get_none()
};
// Check obj type:
if !(objtype::isinstance(&py_obj, &py_type) || objtype::issubclass(&py_obj, &py_type)) {
return Err(vm.new_type_error(
"super(type, obj): obj must be an instance or subtype of type".to_string(),
));
}
// TODO: how to store those types?
vm.ctx.set_attr(inst, "type", py_type);
vm.ctx.set_attr(inst, "obj", py_obj);
Ok(vm.get_none())
}