Skip to content

Commit 19fc202

Browse files
committed
Classmethod/staticmethod - rewrite using structs and new style methods.
1 parent ce120c1 commit 19fc202

File tree

2 files changed

+64
-65
lines changed

2 files changed

+64
-65
lines changed

vm/src/obj/objclassmethod.rs

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,42 @@
1-
use crate::function::PyFuncArgs;
2-
use crate::pyobject::{AttributeProtocol, PyContext, PyResult, TypeProtocol};
1+
use super::objtype::PyClassRef;
2+
use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue};
33
use crate::vm::VirtualMachine;
44

5-
pub fn init(context: &PyContext) {
6-
let classmethod_type = &context.classmethod_type;
7-
extend_class!(context, classmethod_type, {
8-
"__get__" => context.new_rustfunc(classmethod_get),
9-
"__new__" => context.new_rustfunc(classmethod_new)
10-
});
5+
#[derive(Clone, Debug)]
6+
pub struct PyClassMethod {
7+
pub callable: PyObjectRef,
118
}
9+
pub type PyClassMethodRef = PyRef<PyClassMethod>;
1210

13-
fn classmethod_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
14-
trace!("classmethod.__get__ {:?}", args.args);
15-
arg_check!(
16-
vm,
17-
args,
18-
required = [
19-
(cls, Some(vm.ctx.classmethod_type())),
20-
(_inst, None),
21-
(owner, None)
22-
]
23-
);
24-
match cls.get_attr("function") {
25-
Some(function) => {
26-
let py_obj = owner.clone();
27-
let py_method = vm.ctx.new_bound_method(function, py_obj);
28-
Ok(py_method)
29-
}
30-
None => Err(vm.new_attribute_error(
31-
"Attribute Error: classmethod must have 'function' attribute".to_string(),
32-
)),
11+
impl PyValue for PyClassMethod {
12+
fn class(vm: &mut VirtualMachine) -> PyObjectRef {
13+
vm.ctx.classmethod_type()
3314
}
3415
}
3516

36-
fn classmethod_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
37-
trace!("classmethod.__new__ {:?}", args.args);
38-
arg_check!(vm, args, required = [(cls, None), (callable, None)]);
17+
impl PyClassMethodRef {
18+
fn new(
19+
cls: PyClassRef,
20+
callable: PyObjectRef,
21+
vm: &mut VirtualMachine,
22+
) -> PyResult<PyClassMethodRef> {
23+
PyClassMethod {
24+
callable: callable.clone(),
25+
}
26+
.into_ref_with_type(vm, cls)
27+
}
28+
29+
fn get(self, _inst: PyObjectRef, owner: PyObjectRef, vm: &mut VirtualMachine) -> PyResult {
30+
Ok(vm
31+
.ctx
32+
.new_bound_method(self.callable.clone(), owner.clone()))
33+
}
34+
}
3935

40-
let py_obj = vm.ctx.new_instance(cls.clone(), None);
41-
vm.ctx.set_attr(&py_obj, "function", callable.clone());
42-
Ok(py_obj)
36+
pub fn init(context: &PyContext) {
37+
let classmethod_type = &context.classmethod_type;
38+
extend_class!(context, classmethod_type, {
39+
"__get__" => context.new_rustfunc(PyClassMethodRef::get),
40+
"__new__" => context.new_rustfunc(PyClassMethodRef::new)
41+
});
4342
}

vm/src/obj/objstaticmethod.rs

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
1-
use crate::function::PyFuncArgs;
2-
use crate::pyobject::{AttributeProtocol, PyContext, PyResult, TypeProtocol};
1+
use super::objtype::PyClassRef;
2+
use crate::pyobject::{PyContext, PyObjectRef, PyRef, PyResult, PyValue};
33
use crate::vm::VirtualMachine;
44

5-
pub fn init(context: &PyContext) {
6-
let staticmethod_type = &context.staticmethod_type;
7-
extend_class!(context, staticmethod_type, {
8-
"__get__" => context.new_rustfunc(staticmethod_get),
9-
"__new__" => context.new_rustfunc(staticmethod_new),
10-
});
5+
#[derive(Clone, Debug)]
6+
pub struct PyStaticMethod {
7+
pub callable: PyObjectRef,
118
}
9+
pub type PyStaticMethodRef = PyRef<PyStaticMethod>;
1210

13-
// `staticmethod` methods.
14-
fn staticmethod_get(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
15-
trace!("staticmethod.__get__ {:?}", args.args);
16-
arg_check!(
17-
vm,
18-
args,
19-
required = [
20-
(cls, Some(vm.ctx.staticmethod_type())),
21-
(_inst, None),
22-
(_owner, None)
23-
]
24-
);
25-
match cls.get_attr("function") {
26-
Some(function) => Ok(function),
27-
None => Err(vm.new_attribute_error(
28-
"Attribute Error: staticmethod must have 'function' attribute".to_string(),
29-
)),
11+
impl PyValue for PyStaticMethod {
12+
fn class(vm: &mut VirtualMachine) -> PyObjectRef {
13+
vm.ctx.staticmethod_type()
3014
}
3115
}
3216

33-
fn staticmethod_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
34-
trace!("staticmethod.__new__ {:?}", args.args);
35-
arg_check!(vm, args, required = [(cls, None), (callable, None)]);
17+
impl PyStaticMethodRef {
18+
fn new(
19+
cls: PyClassRef,
20+
callable: PyObjectRef,
21+
vm: &mut VirtualMachine,
22+
) -> PyResult<PyStaticMethodRef> {
23+
PyStaticMethod {
24+
callable: callable.clone(),
25+
}
26+
.into_ref_with_type(vm, cls)
27+
}
28+
29+
fn get(self, _inst: PyObjectRef, _owner: PyObjectRef, _vm: &mut VirtualMachine) -> PyResult {
30+
Ok(self.callable.clone())
31+
}
32+
}
3633

37-
let py_obj = vm.ctx.new_instance(cls.clone(), None);
38-
vm.ctx.set_attr(&py_obj, "function", callable.clone());
39-
Ok(py_obj)
34+
pub fn init(context: &PyContext) {
35+
let staticmethod_type = &context.staticmethod_type;
36+
extend_class!(context, staticmethod_type, {
37+
"__get__" => context.new_rustfunc(PyStaticMethodRef::get),
38+
"__new__" => context.new_rustfunc(PyStaticMethodRef::new),
39+
});
4040
}

0 commit comments

Comments
 (0)